web-dev-qa-db-fra.com

Paramétrer une minuterie pour une longue période, c'est-à-dire plusieurs minutes

Je souhaite utiliser l'authentification Firebase avec réagit natif pour Login et Signup, mais j'ai une erreur jaune:

La définition d’un minuteur pour une longue période, c’est-à-dire plusieurs minutes, est un problème de performances et de correction sur Android car le module de minuteur est activé, et les minuteurs ne peuvent être appelés que lorsque l’application est en mode. au premier plan. Voir ( https://github.com/facebook/react-native/issues/12981 ) pour plus d'informations. (Saw setTimeout d'une durée de 111862ms)

Comment puis-je résoudre ce problème?
Je ne veux pas ignorer cela, je veux comprendre cette erreur et la résoudre de la manière la meilleure et la plus classique.
Et voici mon code:

  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>
            )
        }
    }

J'ai signalé à l'équipe Google Firebase : ( https://github.com/firebase/firebase-js-sdk/issues/97 )

44

Josh Crowther, ingénieur logiciel chez Google, a déclaré:

L'utilisation de plusieurs étapes, durée courte, setTimeouts ne résout toutefois pas le problème. Le module Minuterie reste toujours actif et l'application est toujours sujette aux problèmes de performances indiqués dans l'avertissement. Le problème ici est que nous avons des cas d'utilisation qui nécessitent des temps longs, et que react-native n'optimise pas pour ce cas d'utilisation.

Donc le filet de tout ce qui est est: Ce bogue ne peut pas être corrigé ici nous ne pouvons que contourner l'erreur si des solutions de contournement sont disponibles (voir Réglage d'un minuteur pour une longue période, c'est-à-dire plusieurs minutes ) qui désactivent l'avertissement. Faire le travail pour désactiver l'avertissement dans notre code, ne résout pas le problème (au-delà de la désactivation de l'avertissement), et ajoute du code/poids SDK qui est complètement inutile.

Je vous conseillerais de régler le problème mentionné ci-dessus (c'est-à-dire facebook/react-native # 12981) si vous n'êtes pas à l'aise avec la solution de contournement fournie.

9

Cela corrige la boîte jaune et le journal de la console. Il le répare même pour Expo.

Placez simplement le script suivant au début de votre base de code.

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);
  }
};
12
Jam Risser

J'ai le même problème et je pense que c'est un problème de SDK Web firebase, j'ai donc décidé de supprimer le SDK Web Firebase car il s'exécute en js thread, pas de thread natif.

Et j'ai trouvé react-native-firebase . C’est mieux que le SDK Web firebase avec des performances plus élevées et ce problème a disparu

2
Alex Nguyen
import { YellowBox } from 'react-native';

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

Cela ignore l'avertissement pour moi. Vous devriez ajouter ceci au constructeur de chaque page qui affiche l'avertissement.

L'ignorer n'est pas la meilleure approche, mais si vous utilisez la base de données en temps réel Firebase. Ils cherchent à résoudre ce problème avec leur bibliothèque, même si le problème a 2 ans.

2
Lucas Bustamante

Dans login(), il manque une valeur d'intervalle à votre appel setTimeout(). En règle générale, les navigateurs ne déclenchent plus de délais/intervalles si la fenêtre/l'onglet est en arrière-plan ou, du moins, ils ne sont pas censés être à jour. Cela permet d'éviter les comportements de script abusifs et de réduire la consommation d'énergie des scripts susceptibles d'interroger.

Votre code devrait fonctionner en principe. Si l'utilisateur quitte la fenêtre pendant que le chronomètre est en cours d'exécution, il se terminera à son retour. C'est probablement ce que vous voulez du point de vue de l'expérience utilisateur, car les utilisateurs voient la transition plutôt que de se produire en arrière-plan lorsqu'ils ne regardent pas. Cela les aide à maintenir le contexte mental.

La boîte jaune est parce que vous définissez une minuterie excessivement longue en fonction du message (près de deux minutes) et il est peu probable que ce soit contextuellement ce que vous voulez. L'environnement JS vous avertit que ce que vous faites ne correspond probablement pas à vos intentions. Vous pouvez désactiver l'avertissement si c'est ce que vous voulez.

1
Dave Meehan

Une autre approche consiste à utiliser le module react-native-ignore-warnings.

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

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

Cela fonctionne même pour les applications Expo.

Vous l'utiliseriez de la manière suivante. . .

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

ignoreWarnings('Setting a timer');

peut fonctionner avec Android aussi ..?

1
Jam Risser

Je pense que la solution la plus proche à ce problème (jusqu'à ce que RN corrige cela en interne) est la solution mentionnée ici .

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

Étant utilisé - contre un appel Firebase, je reçois toujours un avertissement de boîte jaune (sur settimeout), mais aucun avertissement simultané ne survient par la suite. Je ne suis pas sûr d'appeler ceci à un moment donné, mais cela ne déclenchera peut-être pas le seul avertissement, mais plus aucun avertissement simultané ne sera émis après les appels async de Firebase.

1
Santanu Karar

À Expo, cela ne fonctionnait que pour moi avec ce code, dont je viens de réponse de CopyJosh dans le numéro de Github correspondant:


class App extends Component {
  constructor() {
    super();
    YellowBox.ignoreWarnings(['Setting a timer']);
    console.ignoredYellowBox = ['Setting a timer'];
    const consoleClone = clone(console);
    console.warn = message => {
      if (message.indexOf('Setting a timer') <= -1) {
        consoleClone.warn(message);
      }
    };
  }

  render() {
    return (...);
  }
}

export default App;

La clé est de placer le code dans la fonction App point d’entrée constructor.

0
wscourge

Face au même problème ... On dirait qu’il faudrait cacher l’avertissement pour le moment. Voici le moyen le plus court de le faire:

componentDidMount() { console.disableYellowBox = true; ... }
0
Saurabh Kataria

Contournement du problème avec l'avertissement jaune 'Réglage d'une minuterie'.

copier et importer le fichier suivant (aussi vite que possible ;-))

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);
    };
}
0
Cristo Rabani