programing

장시간(예: 몇 분) 동안 타이머 설정

abcjava 2023. 6. 5. 23:32
반응형

장시간(예: 몇 분) 동안 타이머 설정

native를 사용하고 싶습니다.Login그리고.Signup노란색 오류가 발생했습니다.

타이머를 장시간, 즉 몇 분 동안 설정하는 것은 Android에서 타이머 모듈을 절전 모드로 유지하기 때문에 성능 및 정확성 문제이며, 앱이 전경에 있을 때만 타이머를 호출할 수 있습니다.자세한 내용은 (https://github.com/facebook/react-native/issues/12981) 을 참조하십시오. (SawsetTimeout with duration 111862ms)

어떻게 고칠 수 있을까요?
저는 그것을 무시하고 싶지 않습니다, 저는 이 오류를 이해하고 최선의 표준적인 방법으로 해결하고 싶습니다.
그리고 이것은 나의 코드입니다.

  export default class Login extends Component {
        constructor(props) {
            super(props)
            this.state = {
                email: '',
                password: '',
                response: ''
            }
            this.signUp = this.signUp.bind(this)
            this.login = this.login.bind(this)
        }
        async signUp() {
            try {
                await firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
                this.setState({
                    response: 'Account Created!'
                })
                setTimeout(() => {
                    this.props.navigator.push({
                        id: 'App'
                    })
                }, 1500)
            } catch (error) {
                this.setState({
                    response: error.toString()
                })
            }
        }
        async login() {
            try {
                await firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
                this.setState({
                    response: 'user login in'
                })
                setTimeout(() => {
                    this.props.navigator.push({
                        id: 'App'
                    })
                })

            } catch (error) {
                this.setState({
                    response: error.toString()
                })
            }

        }
        render() {
            return (
                <View style={styles.container}>
                    <View style={styles.containerInputes}>
                        <TextInput
                            placeholderTextColor="gray"
                            placeholder="Email"
                            style={styles.inputText}
                          //  onChangeText={(email) => this.setState({ email })}
                            onChangeText={(email) => {console.log(email);}}
                        />
                        <TextInput
                            placeholderTextColor="gray"
                            placeholder="Password"
                            style={styles.inputText}
                            password={true}
                            onChangeText={(password) => this.setState({ password })}
                        />
                    </View>
                    <TouchableHighlight
                        onPress={this.login}
                        style={[styles.loginButton, styles.button]}
                    >
                        <Text
                            style={styles.textButton}
                        >Login</Text>
                    </TouchableHighlight>
                    <TouchableHighlight
                        onPress={this.signUp}
                        style={[styles.loginButton, styles.button]}
                    >
                        <Text
                            style={styles.textButton}
                        >Signup</Text>
                    </TouchableHighlight>
                </View>
            )
        }
    }

Google Firebase 팀에 보고했습니다. (https://github.com/firebase/firebase-js-sdk/issues/97)

이 문제를 해결하려면...

  1. 음로이다니합으로 합니다.node_modules/react-native/Libraries/Core/Timers/JSTimers.jsjava.

  2. 를 찾습니다.MAX_TIMER_DURATION_MS

  3. 값을 다음으로 변경합니다.10000 * 1000

  4. 자동 형식을 해제한 상태에서 변경 내용을 저장하고 앱을 다시 빌드합니다.

은 https://github.com/firebase/firebase-js-sdk/issues/97#issuecomment-485410026 에서 찾을 수 있습니다.

이 두 줄만 더하면 됩니다.

import { LogBox } from 'react-native';

LogBox.ignoreLogs(['Setting a timer']);

늙은

그러면 노란색 상자와 콘솔 로그가 수정됩니다.그것은 엑스포를 위해 그것을 고칩니다.

코드베이스 시작 부분에 다음 스크립트를 배치하기만 하면 됩니다.

import { YellowBox } from 'react-native';
import _ from 'lodash';

YellowBox.ignoreWarnings(['Setting a timer']);
const _console = _.clone(console);
console.warn = message => {
if (message.indexOf('Setting a timer') <= -1) {
   _console.warn(message);
   }
};

신규

YellowBox더 이상 사용되지 않으며 다음으로 대체됩니다.LogBox

import { LogBox } from 'react-native';
import _ from 'lodash';

LogBox.ignoreLogs(['Warning:...']); // ignore specific logs
LogBox.ignoreAllLogs(); // ignore all logs
const _console = _.clone(console);
console.warn = message => {
if (message.indexOf('Setting a timer') <= -1) {
   _console.warn(message);
   }
};

Google의 Josh Crowther 소프트웨어 엔지니어는 다음과 같이 말했습니다.

그러나 다단계 짧은 기간 setTimeout을 사용하는 것은 실제로 문제를 해결하지 못합니다.타이머 모듈은 여전히 활성 상태를 유지하며 앱은 여전히 경고에 표시된 성능 문제의 영향을 받습니다.여기서 문제가 되는 것은 긴 시간이 필요한 사용 사례가 있으며, 반응 네이티브는 해당 사용 사례에 최적화되지 않는다는 것입니다.

그래서 그 모든 것의 순은 다음과 같습니다.여기서 이 버그를 해결할 수 없습니다. 경고를 비활성화하는 해결 방법이 있는 오류만 해결할 수 있습니다(예: 여러 분 동안 타이머 설정 참조).우리 코드에서 경고를 비활성화하는 작업을 수행하는 것은 문제에 도움이 되지 않으며(경고를 비활성화하는 것 외에) 전혀 불필요한 SDK 코드/무게를 추가합니다.

제공된 해결 방법이 불편할 경우 위에서 언급한 문제(예: facebook/react-native#12981)를 함께 해결하는 것이 좋습니다.

반응 네이티브를 사용하는 경우0.63 여러분의 .App.js the 파일: LogBox react-native .

import { LogBox } from 'react-native';

그리고 당신의 모든 수입품들 후에.App.js파일에서 이 줄을 추가하기만 하면 됩니다. useEffect 호출에서 이 줄을 추가할 필요는 없습니다.

LogBox.ignoreLogs(['Setting a timer for a long period of time'])

자세한 내용은 문서를 참조하십시오.

OR


반응 네이티브를 사용하는 경우0.62 여러분의 .App.js the 파일: YellowBox react-native .

import { YellowBox } from 'react-native';

그리고 당신의 모든 수입품들 후에.App.js파일에서 이 줄을 추가하기만 하면 됩니다. useEffect 호출에서 이 줄을 추가할 필요는 없습니다.

YellowBox.ignoreWarnings(['Setting a timer for a long period of time']);

자세한 내용은 문서를 참조하십시오.

노란색 경고 '타이머 설정' 문제를 해결합니다.

다음 파일 복사 및 가져오기(최대한 빨리 ;-)

import {Platform, InteractionManager} from 'react-native';

const _setTimeout = global.setTimeout;
const _clearTimeout = global.clearTimeout;
const MAX_TIMER_DURATION_MS = 60 * 1000;
if (Platform.OS === 'android') {
    // Work around issue `Setting a timer for long time`
    // see: https://github.com/firebase/firebase-js-sdk/issues/97
    const timerFix = {};
    const runTask = (id, fn, ttl, args) => {
        const waitingTime = ttl - Date.now();
        if (waitingTime <= 1) {
            InteractionManager.runAfterInteractions(() => {
                if (!timerFix[id]) {
                    return;
                }
                delete timerFix[id];
                fn(...args);
            });
            return;
        }

        const afterTime = Math.min(waitingTime, MAX_TIMER_DURATION_MS);
        timerFix[id] = _setTimeout(() => runTask(id, fn, ttl, args), afterTime);
    };

    global.setTimeout = (fn, time, ...args) => {
        if (MAX_TIMER_DURATION_MS < time) {
            const ttl = Date.now() + time;
            const id = '_lt_' + Object.keys(timerFix).length;
            runTask(id, fn, ttl, args);
            return id;
        }
        return _setTimeout(fn, time, ...args);
    };

    global.clearTimeout = id => {
        if (typeof id === 'string' && id.startsWith('_lt_')) {
            _clearTimeout(timerFix[id]);
            delete timerFix[id];
            return;
        }
        _clearTimeout(id);
    };
}
import { YellowBox } from 'react-native';

construct() {
    YellowBox.ignoreWarnings(['Setting a timer']);
}

이것은 저에 대한 경고를 무시합니다.경고를 표시하는 모든 페이지의 생성자에 이 정보를 추가해야 합니다.

이를 무시하는 것이 최선의 방법은 아니지만 Firebase Realtime Database를 사용하는 경우.그들은 이 문제가 2년이 지났지만 도서관에서 이 문제를 해결하는 것을 검토하고 있습니다.

제가 한 일과 그것이 저와 함께 작동하고 있지만 여전히 저는 그것이 좋은 관행인지 아닌지 모르겠습니다.

파일로 이동

node_modules\react-native\Libraries\코어\타이머\JSTIMers.js

.const MAX_TIMER_DURATION_MS = 60 * 1000 * 더 이상 나오지 .

저도 같은 이슈를 받았고 파이어베이스 웹 SDK의 문제인 것 같아서 파이어베이스 웹 SDK는 react-native 스레드가 아닌 js 스레드에서 실행되기 때문에 폐기하기로 했습니다.

그리고 저는 반응 네이티브 화력 기지를 찾았습니다.더 높은 성능을 가진 파이어베이스 웹 SDK보다 낫고 이 문제는 사라졌습니다.

동일한 문제에 직면하고 있습니다.당분간은 경고를 숨겨야 할 것 같습니다.가장 빠른 방법은 다음과 같습니다.

componentDidMount() { console.disableYellowBox = true; ... }

Firebase/Firestore 사용자: 경고를 마스크/숨기기보다는 REST API로 되돌렸습니다.매력적으로 작동합니다 :)

  • 사용중다니입▁the를 사용하고 있습니다.firebase 파일에 노드
  • firestore를 위해 을 사용하고 호출도 합니다).atob그리고.bto

아래의 스니펫은 HTTP 클라이언트를 사용합니다(https://github.com/hardcodet/httpclient-js), 당신은 당신에게 맞는 모든 것을 사용할 수 있습니다(예: fetch 또는 axios).

// Firebase App (the core Firebase SDK) is always required and
// must be listed before other Firebase SDKs
import * as firebase from "firebase/app";
import "firebase/auth";
import {LoginStatus} from "./LoginStatus";
import {auth, User} from "firebase";
import {ApiResponse, DelegateBearerAuthClient, HttpClient} from "@hardcodet/httpclient";
import {Env} from "../../Env";



export class FirebaseClient {

    /**
     * Creates a simple API client to use with Firestore.
     * We don't want to use the JS package's implementation since it has issues with
     * long-running timers - see https://github.com/firebase/firebase-js-sdk/issues/97
     * @param idToken The user's ID token as retrieved through firebase auth
     */
    private static getFirestoreClient(idToken: string) {
        const projectId = Env.firebaseProjectId;
        const baseUri = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/`

        const authClient = new DelegateBearerAuthClient(async () => idToken);
        return new HttpClient(baseUri, {authClient});
    }


    /**
     * Use firebase auth for login etc. because lazy.
     */
    public static async userLogin(email: string, password: string): Promise<User> {
        try {
            const credentials: firebase.auth.UserCredential = await auth().signInWithEmailAndPassword(email, password);
            return credentials.user;
        } catch (error) {
            console.error(error);
            return undefined;
        }
    }


    private static resolveStatus(errorCode: string): { user: User, status: LoginStatus } {
        switch (errorCode) {
            case "auth/invalid-email":
                return {user: undefined, status: LoginStatus.InvalidEmailAddress};
            case "auth/user-not-found":
                return {user: undefined, status: LoginStatus.UnknownUserId};
            case "auth/wrong-password":
                return {user: undefined, status: LoginStatus.WrongPassword};
            case "auth/email-already-in-use":
                return {user: undefined, status: LoginStatus.EmailAddressAlreadyInUse};
            case "auth/weak-password":
                return {user: undefined, status: LoginStatus.WeakPassword};
            case "auth/user-disabled":
                return {user: undefined, status: LoginStatus.UserDisabled};
            case "auth/expired-action-code":
                return {user: undefined, status: LoginStatus.InvalidActionCode};
            default:
                return {user: undefined, status: LoginStatus.Undefined};
        }
    }


    /**
     * Resolve the user's keys from the backend.
     */
    public static async getSomeUserData(firebaseUserId: string, idToken: string): Promise<...> {

        const client: HttpClient = FirebaseClient.getFirestoreClient(idToken);

        // userData here is the name of my collection in firestore. i'm using the user ID as the document ID
        var result = await client.getAs<any>(`userData/${firebaseUserId}?key=${Env.firebaseApiKey}`);
        if (result.success) {
            const json = result.value;
            const foo = json.fields.foo.stringValue;
            const bar = json.fields.bar.stringValue;
            return ...
        } else {
            if (result.notFound) {
                // that document with that key doesn't exist
                console.warn("no document with key " + firebaseUserId);
                return undefined;
            }
            throw result.createError();
        }
    }


    public static async writeSomeData(idToken: string, firebaseUserId: string, foo: string, bar: string): Promise<...> {

        const data = {
            "fields": {
                "foo": {
                    "stringValue": foo
                },
                "bar": {
                    "stringValue": bar
                }
            }
        };

        // again, just do an HTTP post, use the firebase user ID as the document key
        const client: HttpClient = FirebaseClient.getFirestoreClient(idToken);
        const result: ApiResponse = await client.post(`userData?documentId=${firebaseUserId}&key=${Env.firebaseApiKey}`, data);

        if (result.success) {
            return ...
        } else {
            throw result.createError();
        }
    }


    /**
     * Gets the currently logged in user, if any.
     */
    public static getCurrentUser(): User {
        return auth().currentUser;
    }



    public static async sendPasswordReset(email: string): Promise<LoginStatus> {

        try {
            await auth().sendPasswordResetEmail(email);
            return LoginStatus.Success;
        } catch (error) {
            return FirebaseClient.resolveStatus(error.code).status;
        }
    }


    /**
     * Clears the current user from the session.
     */
    public static async signOut() {
        await auth().signOut();
    }
}

에 하십시오.idToken- 은 단순히 파이어베이스에서 입니다. - 이은단당 - 것이신파이어베이에서스내리는다매니토큰입 ID 개수변순히다.User클래스:

        const user: User = await FirebaseClient.userLogin("me@domain.com", "mypassword");

        const idToken= await user.getIdToken(false);
        const data = await FirebaseClient.getSomeUserData(user.uid, idToken);

login(),당신의.setTimeout()호출에 간격 값이 없습니다.일반적으로 브라우저는 창/탭이 백그라운드에 있거나 적어도 시기적절하지 않을 것으로 예상되는 경우 시간 초과/간격을 실행하지 않습니다.이는 잘못된 스크립트 동작을 방지하고 폴링 중인 스크립트의 전력 소비를 줄이기 위한 것입니다.

사용자의 코드는 원칙적으로 작동해야 합니다. 타이머가 실행되는 동안 사용자가 창에서 벗어나면 사용자가 돌아올 때 완료됩니다.사용자가 보지 않을 때 백그라운드에서 발생하는 것이 아니라 전환을 보기 때문에 UX 관점에서 원하는 것일 수 있습니다.그것은 그들이 정신적 맥락을 유지하도록 도와줍니다.

노란색 상자는 메시지에 따라 지나치게 긴 타이머를 설정하고 있기 때문에(거의 2분) 상황에 따라 원하는 타이머가 아닐 수 있습니다.JS 환경은 당신이 하고 있는 일이 당신이 의도하는 것과 같지 않다는 것을 경고합니다.원하는 경우 경고를 음소거할 수 있습니다.

저는 이 문제에 대한 가장 가까운 해결책이 (RN이 내부적으로 이 문제를 해결할 때까지) 여기서 언급한 해결책이라고 생각합니다.

// add this code to your project to reset all timeouts
const highestTimeoutId = setTimeout(() => ';');
for (let i = 0; i < highestTimeoutId; i++) {
    clearTimeout(i); 
}

사용 중 - Firebase 호출에 대해 여전히 노란색 상자 경고(설정 시간 초과 시)를 하나 받지만, 그 이후에는 동시 경고가 발생하지 않습니다.이것을 호출하면 유일한 경고도 트리거되지 않을 수도 있지만, 파이어베이스의 경고 이후 더 이상 동시 경고가 발생하지 않습니다.async전화가 걸려오는 전화.

또 다른 접근 방식은 반응 네이티브 무시 경고 모듈을 사용하는 것입니다.

https://github.com/jamrizzi/react-native-ignore-warnings

https://www.npmjs.com/package/react-native-ignore-warnings

이것은 Expo 앱에서도 작동합니다.

당신은 그것을 다음과 같은 방법으로 사용할 것입니다.

import ignoreWarnings from 'react-native-ignore-warnings';

ignoreWarnings('Setting a timer');

안드로이드로도 실행할 수 있습니까?

이 코드로 경고를 비활성화합니다.

import { YellowBox } from 'react-native';
YellowBox.ignoreWarnings(['Setting a timer']);

언급URL : https://stackoverflow.com/questions/44603362/setting-a-timer-for-a-long-period-of-time-i-e-multiple-minutes

반응형