La configuración de temporizadores para varios minutos no se maneja correctamente en React Native en Android: mantiene el módulo Timing activo en lugar de depender de que el sistema nos despierte cuando el temporizador debería sonar.
Deberíamos explorar la posibilidad de establecer un límite en el que deleguemos a AlarmManager y Handler.postDelayed en lugar de manejar los temporizadores mediante framecallbacks.
¡Gran mejora!
esto ayudaría con socket.io que mantiene un temporizador de 85000ms
por defecto. En el maestro RN, el umbral es 60000ms
.
Y Firebase, que también usa temporizadores largos.
Recibo la siguiente advertencia mientras uso la biblioteca de base de fuego
Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info.
(Saw setTimeout with duration 111862ms)
Cómo deshacerse de esta advertencia ...
También recibo la siguiente advertencia mientras uso la biblioteca de base de fuego. ¿Alguien sabe cómo solucionar este problema?
También recibo esta advertencia con firebase.
"firebase": "^3.9.0",
"react-native": "0.44.0"
Mismo problema ( 85000ms
) pero sin firebase
. Mi lista de paquetes:
"dependencies": {
"apisauce": "0.11.0",
"format-json": "1.0.3",
"lodash": "4.17.4",
"markdown-it": "^8.3.1",
"native-base": "^2.1.3",
"normalizr": "^3.2.2",
"prop-types": "^15.5.10",
"querystringify": "1.0.0",
"ramda": "0.23.0",
"react": "16.0.0-alpha.6",
"react-markdown": "^2.5.0",
"react-native": "0.44.0",
"react-native-animatable": "1.2.0",
"react-native-config": "0.4.2",
"react-native-device-info": "0.10.2",
"react-native-drawer": "2.3.0",
"react-native-htmlview": "0.9.0",
"react-native-i18n": "1.0.0",
"react-native-linear-gradient": "^2.0.0",
"react-native-photo-view": "^1.2.0",
"react-native-router-flux": "3.39.1",
"react-native-scrollable-tab-view": "*",
"react-native-share": "^1.0.20",
"react-native-vector-icons": "4.1.1",
"react-navigation": "^1.0.0-beta.9",
"react-redux": "5.0.4",
"redux": "3.6.0",
"redux-persist": "4.6.0",
"redux-saga": "0.15.3",
"reduxsauce": "0.4.1",
"seamless-immutable": "7.1.2"
},
"devDependencies": {
"ava": "^0.18.2",
"babel-eslint": "^7.1.1",
"babel-preset-es2015": "^6.18.0",
"enzyme": "^2.6.0",
"husky": "^0.13.1",
"ignite-animatable": "^0.3.1",
"ignite-dev-screens": "^2.0.0-beta.9",
"ignite-i18n": "^0.1.1",
"ignite-ir-boilerplate-2016": "^0.2.2",
"ignite-vector-icons": "^0.2.1",
"mockery": "^2.0.0",
"nyc": "^10.1.2",
"react-addons-test-utils": "^15.3.1",
"react-dom": "^15.4.0",
"react-native-mock": "^0.3.1",
"reactotron-apisauce": "^1.7.0",
"reactotron-react-native": "^1.7.0",
"reactotron-redux": "^1.7.0",
"reactotron-redux-saga": "^1.7.0",
"snazzy": "^6.0.0",
"standard": "^8.6.0"
}
Estoy experimentando un problema similar al usar 0.44.0 en Android. Tampoco estoy usando firebase:
Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info. (Saw setTimeout with duration 85000ms)
Hola chicos ... me preguntaba si hay alguna solución rápida para esto. Estoy usando:
react-native 0.44
react 16.0.0-alpha.6
feathers-socketio 1.6.0
Es muy molesto aparecer mientras estoy desarrollando ... ¿De todos modos puedo ocultar la advertencia por ahora?
El mismo problema aquí con firebase 3.9.0
Si le molesta, solo agregue console.ignoredYellowBox = ['Setting a timer'];
@ skv-headless Opinión entrante. :)
En mi opinión, esa actitud hacia los problemas debe desaparecer. Lo he visto aparecer con más frecuencia y hace que la gente ignore las advertencias. Son advertencias. Te advierten. No los ignore, haga algo. He visto aplicaciones en las que se ignoran todas las advertencias, incluso los avisos de desaprobación. Luego, su aplicación se rompe y se pregunta por qué.
En este caso, puede configurar estos tiempos de espera y reducirlos, o configurar un enfoque diferente para tratar con ellos. Tal vez incluso moleste a los encargados de las bibliotecas y pídales que le ayuden a encontrar una solución.
Mi consejo es seguir este hilo hasta que alguien inteligente encuentre una solución real, para que luego pueda informarse con esa respuesta. Y luego, tal vez, mientras tanto (si no puede o no quiere abordar el problema) ignore las advertencias.
TL; DR;
Sí, puede ignorar las advertencias temporalmente. Simplemente verifique de vez en cuando para ver cuál es el estado y si se requiere alguna acción.
@imamatorio creo que es de Rectotron
Creo que es por Rectotron
Si es así, esta advertencia puede simplemente ignorarse.
... sin embargo, mi emulador de Android se vuelve lento a veces, tal vez sea una de las razones.
@imamatorio Espero que la verdadera solución sea igual de fácil
Hola, creo que encontré la solución:
En primer lugar, debe encontrar el siguiente archivo en su proyecto: bibliotecas / Core / Timers / JSTimer; js
Ábralo y solo tiene que cambiar esta constante MAX_TIMER_DURATION_MS, para aumentar por encima de su duración, ¡escribió al final de la advertencia!
@nicolasZZ hola, Gracias por la solución. pero ¿es una buena práctica modificar la biblioteca JSTimer
lugar de nuestro propio código?
@nicolasZZ @AmroAly En mi opinión, esta solución no es una buena práctica porque es muy inestable, lo mejor es ignorar la alerta mientras se lanza la solución oficial.
console.ignoredYellowBox = [
'Setting a timer'
]
la solución de @ skv-headless es buena pero en mi caso solo funciona con "enter" entre paréntesis
@rigobcastro Gracias que esconde las molestas alertas.
@ DZuz14 Sería genial si pudieras enviar un PR o al menos iniciar la conversación. Gracias 👍
hola ~
Usé socket.io. nodejs and RN44 or RN 45
Vi una advertencia de este temporizador.
Encontré esta solución
reference reactotron PR
servidor personal nodejs y scoket.io
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server, {pingTimeout: 30000})
¡Gracias!
Tengo un proyecto nativo de reacción simple para Android y estoy usando la autenticación de base de fuego con reaccionar nativo para iniciar sesión y registrarse, pero recibí ese error amarillo, ¿qué debo hacer? Enlace de mi pregunta en stackoverslow (https://stackoverflow.com/questions/44603362/setting-a-timer-for-a-long-period-of-time-ie-multiple-minutes)
Gracias @ DZuz14
Recibí este error cuando ejecuto react-native run-android
D:\Projects 2016\Web\Android\mohajerkade-android\android\app\src\main\java\com\mohajerkade\AlarmManagerModule.java:40: error: cannot find symbol
Intent intent = new Intent(context, AlarmReceiver.class);
^
symbol: class AlarmReceiver
location: class AlarmManagerModule
1 error
:app:compileDebugJavaWithJavac FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
Quiero usar firebase auth con react native para iniciar sesión y registrarse, pero obtuve ese error amarillo,
1: ¿Qué es este módulo exactamente?
2: ¿Por qué mi proyecto necesita este módulo?
Le pregunté a stackoverflow a través de este enlace: (https://stackoverflow.com/questions/44603362/setting-a-timer-for-a-long-period-of-time-ie-multiple-minutes)
Informé al equipo de Google Firebase a través de este enlace: (https://github.com/firebase/firebase-js-sdk/issues/97)
@ DZuz14 Recibí la misma pregunta que @saeedhei .
Básicamente estamos usando el módulo de nodo firebase
que usa estos temporizadores de largo período.
Agregar su módulo no es suficiente, supongo, en realidad tenemos que reescribir el código dentro del módulo de nodo firebase
para usar sus alarmas en lugar de los temporizadores de Javascript, ¿verdad?
Gracias @ DZuz14
Entonces, si observa el paquete npm llamado firebase
, encontrará que utiliza setTimeout en bastantes lugares. Esto está bien, ya que la biblioteca se escribió para sitios web y servidores node.js. react-native
es una especie de servidor node.js pero se ejecuta en un teléfono, y como señala correctamente la advertencia, los temporizadores de Javascript de larga ejecución no son buenos en este entorno y pueden agotar la batería y tener otros efectos secundarios no deseados .
Así que supongo que tenemos que convencer a los chicos de Firebase de que cambien su enfoque y distribuyan un paquete hecho especialmente por react-native
.
@BerndWessels https://www.npmjs.com/package/react-native-firebase ¿Has mirado esto? Dice que permite que firebase se ejecute en el hilo nativo. No estoy seguro de cuán cierto es eso, pero podría valer la pena echarle un vistazo. Incluso podría estar usando eso, no estoy seguro.
@ DZuz14 Gracias, lo comprobaré.
console.ignoredYellowBox = [
'Configurar un temporizador'
]
@rigobcastro ¿Dónde puedo ingresar o pegar este código?
@ Jazz747 En la parte superior de su archivo de configuración, por ejemplo, app.js, index.android.js o index.ios.js
console.ignoredYellowBox = [ 'Setting a timer' ]
Este código solo oculta la advertencia dentro de reaccionar nativo.
¿Qué tal la advertencia dentro de la consola del navegador?
¿Alguien sabe si alguien del equipo de enfermeras registradas o de la comunidad está trabajando en una solución a este problema?
La ventana emergente de advertencia redirige a este problema, pero no puedo encontrar ninguna solución adecuada aquí además de ocultar la advertencia, que no es una solución en absoluto. ¿Alguna idea o sugerencia?
@SuhairZain Todo parece indicar que son errores de bibliotecas externas a RN
@rigobcastro Esta advertencia se puede reproducir fácilmente con una llamada setInterval()
con un tiempo suficientemente largo (que fue de 5 minutos en mi caso). Entonces diría que esto no es algo causado por bibliotecas de terceros.
Por cierto, desde entonces encontré una biblioteca aquí: react-native-background-timer que me ayuda a hacer el trabajo.
@SuhairZain sí, ¡tienes razón! mi problema fue con una biblioteca de terceros, pero el propietario solucionó el error (imagino que solo cambiaron algunos setInterval()
) y la advertencia desapareció.
Buena recomendación, gracias.
tengo el mismo problema aquí. Y aún así podría entender cómo debo manejar este problema.
rn: 0.45.1
base de fuego: 4.1.3
Estimado @escalepion , informé al equipo de firebase: (https://github.com/facebook/react-native/issues/12981#issuecomment-309595327)
@escalepion Si su problema es establecer temporizadores de larga duración, por favor, eche un vistazo a mi comentario anterior y vea si le ayuda.
@SuhairZain lo siento, no pude entender que ¿cómo puedo usar setInterval o react-native-background-timer :( dónde y cómo escribiré el código? ¿Tienes un ejemplo?
¿Alguien tiene algún consejo sobre cómo averiguar qué biblioteca está causando el daño? Recientemente actualicé RN a 0.46 y de repente apareció este error. Tengo bastantes bibliotecas en mi proyecto y solo puedo pensar en investigarlas una por una, lo que obviamente no es lo ideal.
¡Salud!
@ abeltje1 , si averigua cómo solucionar este problema, ¿podría, por favor, actualizar aquí?
@liketurbo seguro que lo haré
Tengo este problema junto con redux-saga
para revalidar el token de API cada 30 minutos.
Por lo tanto, en este caso, esperar tanto tiempo es realmente correcto. Y supongo que hay otros escenarios de los que se espera una larga espera.
Entonces mi pregunta es, ¿por qué es esto una advertencia? ¿Qué puede pasar / romper? ¿No se supone que pueda utilizar ningún LLT (transacciones de larga duración)?
Si LLT está bien. ¿Cuál sería el mejor enfoque para manejar este problema? ¿Ampliando el tiempo de AlarmManager?
Gracias por adelantado ;)
Tengo el mismo problema que @sospedra. Estoy usando redux-saga
y tengo una saga que actualiza algunos datos en la aplicación en segundo plano cada 3 minutos, por lo que la saga incluye el código yield call(delay, 3 * 60000);
. Como resultado, recibo este error de "Configuración de un temporizador durante un largo período de tiempo ...".
También me pregunto cuál es el enfoque sugerido para algo como esto. ¿Qué problemas me encontraré si dejo mi código funcionando de esta manera? El mensaje de error implica que podría haber problemas de rendimiento y quizás que el temporizador no se activará en el momento correcto si la aplicación está en segundo plano.
Si es probable que haya problemas con este código al configurar un temporizador de 3 minutos, ¿qué solución alternativa lograría la misma funcionalidad y no se encontraría con estos problemas?
sigue teniendo el mismo problema.
Creo que la única solución es pasar al desarrollo nativo de Android
¿El problema aún no se puede resolver? ¿Alguien encontró la solución?
Recibo una advertencia mientras uso firebase.
Si el problema no es de una biblioteca de terceros, sino de establecer un tiempo de espera prolongado, una buena solución es usar la biblioteca react-native-background-timer . Su README también contiene un ejemplo simple.
Desafortunadamente , si el problema proviene de una biblioteca de terceros, probablemente no tenga otra solución que encontrar el lugar donde se llama al setTimeout y plantear un problema / enviar un PR para usar la biblioteca mencionada anteriormente , pruebe mi posible solución a continuación en https://github.com/facebook/react-native/issues/12981#issuecomment -331074444 y pruebe si funciona para usted.
Por favor, haga un gran tiempo de espera en Android también.
react-native-background-timer es una buena solución, como dijo @SuhairZain . esto puede borrar el mensaje de advertencia
Recibo esta advertencia cuando uso socket.io
porque socket.io tiene un temporizador de 85ms
FWIW, esto solo me sucede cuando uso Reactotron mientras desarrollo ...
Me volvió loco por un tiempo, tengo que admitirlo pero sabía que no podía ignorar el mensaje.
Ya no estoy trabajando en el proyecto con el que tuve este problema, por lo que realmente no puedo probar si este enfoque funciona, pero debería hacerlo, al menos en teoría. Si el error proviene de un módulo de terceros que usa setTimeout o setInterval con un retraso prolongado, esto debería poder solucionar el problema. Lo que hace es parchear el setTimeout global y setInterval para usar react-native-background-timer en su lugar:
import BackgroundTimer from 'react-native-background-timer';
setTimeout = BackgroundTimer.setTimeout;
setInterval = BackgroundTimer.setInterval;
clearTimeout = BackgroundTimer.clearTimeout;
clearInterval = BackgroundTimer.clearInterval;
Escriba este código en algún lugar de su inicialización inicial, preferiblemente index.android.js o index.ios.js lo antes posible. Si alguien puede probar esto, sería muy apreciado.
@SuhairZain : tu sugerencia me está funcionando hasta ahora, con algunos ajustes:
setTimeout = BackgroundTimer.setTimeout.bind(BackgroundTimer)
setInterval = BackgroundTimer.setInterval.bind(BackgroundTimer)
clearTimeout = BackgroundTimer.clearTimeout.bind(BackgroundTimer)
clearInterval = BackgroundTimer.clearInterval.bind(BackgroundTimer)
@levity agregué tu código a mi app.js, pero obtuve esto
undefined no es un objeto (evaluando 'RNBackgroundTimer.setTimeout')
@realtebo parece que es posible que no hayas completado la instalación de react-native-background-timer como se describe en su README ejecutando react-native link
o usando CocoaPods.
@levity : ¿te refieres a ejecutar react-native link
?
npm install -g react-native-cli
enlace nativo de reacción
Escaneo de carpetas para enlaces simbólicos en C: \ Users \ realtebo \ Downloads \ manager2 \ node_modules (54ms)
react-native link
no se puede usar en proyectos de Create React Native App. Si necesita incluir una biblioteca que se base en código nativo personalizado, es posible que primero deba expulsarla. Consulte https://github.com/react-community/create-react-native-app/blob/master/EJECTING.md para obtener más información.
No quiero expulsar ... así que ... ¿qué puedo hacer?
Oh, lo siento, no sé cómo ayudarte con un proyecto de Create React Native App. Yo nunca lo he usado.
Hola,
Tengo algunos problemas con react-native: ^0.49.3
...
cf. https://github.com/ocetnik/react-native-background-timer/issues/65
Espero que puedas ayudar, gracias por tu tiempo;)
Hola, tengo el mismo problema que estoy usando 0.49
, apareció después de hacer esto
export function saveUserData(userInfo){
return (dispatch) => {
dispatch(saveDataRequest())
const userId = firebase.auth().currentUser.uid;
return firebase.database().ref('users/' + userId).set(userInfo)
.then(() => {
dispatch(saveDataSuccess());
dispatch(NavigationActions.navigate({ routeName: 'TabContactNavigation' }))
})
.catch((error) => {
dispatch(saveDataFailure(error))
});
}
}
Lo anterior es Action
en redux, que también usa redux-thunk
.. Cuando se hace clic en un botón para guardar datos de un formulario en firebase
cuando se guarda correctamente, se envía saveDataSuccess()
y luego navegue a la siguiente pestaña.
Ahora sospecho que el problema parece estar aquí const userId = firebase.auth().currentUser.uid
pero no estoy seguro. Aquí hay una captura de pantalla del problema. (la aplicación funciona bien pero aparece esta advertencia, no sé si debería simplemente ignorarla) o tal vez estoy haciendo algo mal aquí, necesito su ayuda, gracias
oye, la advertencia es sobre setTimeout ¿lo estás usando en tu componente?
y sí, la línea const userId = firebase.auth (). currentUser.uid; no está funcionando, eso es una promesa y cuando usa userId todavía no viene.
una mejor manera de hacerlo es obtener el userId del actionCreator, ya está enviando la variable userInfo, intente esto:
Asumiré que userInfo proviene del inicio de sesión de autenticación de firebase, por lo que tiene el uid en él
función de exportación saveUserData (userInfo) {
return (envío) => {
despacho (saveDataRequest ())
// const userId = firebase.auth (). currentUser.uid;
devolver firebase.database (). ref ('usuarios /' + userInfo.uid) .set (userInfo)
.entonces (() => {
despacho (saveDataSuccess ());
despacho (NavigationActions.navigate ({routeName: 'TabContactNavigation'}))
})
.catch ((error) => {
despacho (saveDataFailure (error))
});
}
}
espero que esto pueda ayudar, y lo siento por mi mal inglés = P
Felicidad
El 23/10/2017, a las 23:59, Yasir [email protected] escribió:
Hola, tengo el mismo problema que estoy usando 0.49, apareció después de hacer esto
función de exportación saveUserData (userInfo) {
return (envío) => {
despacho (saveDataRequest ())
const userId = firebase.auth (). currentUser.uid;
devolver firebase.database (). ref ('usuarios /' + userId) .set (userInfo)
.entonces (() => {
despacho (saveDataSuccess ());
despacho (NavigationActions.navigate ({routeName: 'TabContactNavigation'}))
})
.catch ((error) => {
despacho (saveDataFailure (error))
});
}
}
Lo anterior es Action in redux, que también usa redux-thunk. Cuando se hace clic en un botón para guardar datos de un formulario en firebase, cuando se guarda correctamente, envía saveDataSuccess () y luego navega a la siguiente pestaña.
Ahora sospecho que el problema parece estar aquí const userId = firebase.auth (). CurrentUser.uid pero no estoy seguro. Aquí hay una captura de pantalla del problema. (la aplicación funciona bien pero aparece esta advertencia, no sé si debería simplemente ignorarla) o tal vez estoy haciendo algo mal aquí, necesito su ayuda, graciashttps://user-images.githubusercontent.com/12644122/31925375-94b7c464-b89d-11e7-889d-e9d00866ff73.png
https://user-images.githubusercontent.com/12644122/31925386-9e9bf3c4-b89d-11e7-9eaa-65147879629f.png
-
Estás recibiendo esto porque estás suscrito a este hilo.
Responda a este correo electrónico directamente, véalo en GitHub https://github.com/facebook/react-native/issues/12981#issuecomment-338874018 , o silencie el hilo https://github.com/notifications/unsubscribe-auth/ AHhM1oYWKrWSOZsm-8hjp4Q6qJSfqraUks5svW6-gaJpZM4Mf0Z0 .
Por lo general, guardo en una tienda redux el userinfo.
Así que simplemente vuelvo a utilizar según sea necesario.
... pero ... en una situación similar, tengo el mismo problema idéntico con el tiempo de espera
El mismo problema con la biblioteca react-native-signalr (300000ms)
Opciones del servidor socket.io
pingTimeout (60000) + pingInterval (25000) <= 60000
¿Alguna actualización sobre cómo deberíamos lidiar con esto en Android? Todavía lo entiendo, sin usar setTimeout tampoco ...
Solo para continuar con mi comentario anterior (de agosto) que creo que resume los sentimientos de toda la gente de aquí: estamos de acuerdo con esta cosa de AlarmManager es solo que queremos conocer el mejor enfoque para manejar transacciones de larga duración
cc @shergin @cpojer @javache @hramos
Una solución para react-native-signalr (ms-signalr-client) en Android es anular el intervalo de ping predeterminado (300000):
connection.start({ pingInterval: 5000, jsonp: true, transport: ['webSockets', 'serverSentEvents', 'longPolling']}).done(() => {
console.log('Now connected, connection ID =' + connection.id)
})
El mismo problema con react-native-pomelo (80000ms)
console.ignoredYellowBox = ['Setting a timer'];
Esto es bastante seguro como solución, ya que seguirá recibiendo la advertencia en la consola de Chrome cuando depure de forma remota
¿Dónde está exactamente el mejor lugar para colocar el código ignorado de la consola?
- no importa, obtuve una pista del stackexchange vinculado, agregado a mi App.js de la siguiente manera:
class App extends Component {
constructor() {
super();
console.ignoredYellowBox = [
'Setting a timer'
];
}
...
}
````
and also tried in my index.js as <strong i="8">@haikyuu</strong> just recommended..
importar {AppRegistry} desde 'react-native';
importar la aplicación desde './App';
console.ignoredYellowBox = [
'Configurar un temporizador'
];
AppRegistry.registerComponent ('administrador', () => Aplicación);
`` ``
trabajó en ambos
@CopyJosh puede ponerlo en su archivo de entrada: index.js
¿Entonces no hay una solución real para esto todavía? Han pasado más de 8 meses ...
?
Resolvamos esto entonces. Probablemente tendríamos que averiguar:
A.) Una API extensible fácil que se puede llamar a través del código React. Creo que sería prudente abordar tal vez hacer que solo uno de los métodos de AlarmManagers funcione. Por ejemplo, llamar al siguiente método en su código React Native establecería una alarma con el AlarmManager nativo de los dispositivos Android.
AlarmMgr.setInexactRepeating(arg1, arg2...)
B.) La implementación real de hacer que esto funcione. Hasta donde yo sé, configurar una alarma con AlarmManager envía lo que se llama una "intención pendiente" al servicio AlarmManager. Le dice a AlarmManager que le gustaría ejecutar algún tipo de "tarea" en el futuro. Me parece que necesitaría que AlarmManager (o un Método React Java personalizado) envíe algún tipo de datos a su código JavaScript, indicándole qué código ejecutar después de que suene la alarma.
¿Alguien está dispuesto a abordar este problema? Se puede leer más en AlarmManager aquí .
Por cierto, ¿esta ineficiencia (relacionada con tiempos de espera largos de varios minutos) es un problema nuevo solo para las versiones RN> 0.43? ¿O es solo que la advertencia se escupe desde RN> 0.43? Migré de 0.43.xa 0.47.xy comencé a ver la advertencia. Supuse que la ineficiencia siempre había estado ahí y que RN acababa de empezar a advertirme sobre eso ahora ...
sin embargo, desde la migración hace unos días, ¡también noté que mi aplicación consume mucha más batería en mi teléfono! (y las otras características en la diferencia no son culpables obvias)
Hola @astreet , ¿quizás todavía recuerdas a qué te https://github.com/facebook/react-native/commit/3637bce479 ?
Recientemente, se volvió bastante molesto para mí después de que comencé a usar una biblioteca que establece un temporizador recurrente de 2 minutos, así que comencé a profundizar en él para comprender por qué se agregó esta advertencia en primer lugar.
Ahora me preocupa esta frase: "mantiene despierto el módulo de temporización". A lo que creo que te estarás refiriendo es a que el módulo Timer está configurando la devolución de llamada del coreógrafo. Aunque la devolución de llamada parece estar configurada independientemente de si tenemos el temporizador o no. Vea la parte del código relevante aquí: https://github.com/facebook/react-native/blob/1e8f3b11027fe0a7514b4fc97d0798d3c64bc895/ReactAndroid/src/main/java/com/facebook/react/modules/core/Timing.java#L106
No hay un código para detener la devolución de llamada cuando no hay temporizadores programados y no hay un código para iniciar la programación cuando se agrega el temporizador. La devolución de llamada se suspende solo cuando la aplicación pasa a segundo plano y se restaura cuando se vuelve a colocar en primer plano.
Como consecuencia, la devolución de llamada del coreógrafo se pone en cola para cada fotograma, independientemente de si tenemos un temporizador para un período largo, un período corto o ningún temporizador configurado. No veo cómo la configuración del temporizador largo puede afectar el rendimiento en ese caso. Entonces, ¿significa que la advertencia no es necesaria?
En cuanto a que configurar el temporizador largo es un "problema de corrección", creo que se refiere al hecho de que los temporizadores solo se llamarán en el estado de la aplicación en primer plano (por lo tanto, cuando lo configure durante un tiempo prolongado en el futuro y la aplicación ingrese en bg o no se ejecutará o se ejecutará cuando la aplicación pase a primer plano, lo que puede ser mucho más tarde de lo esperado). Aunque creo que este es el mismo caso para iOS, donde no mostramos la advertencia
En socket.io, el bucle de ping predeterminado es 85000ms, = pingInterval (25000ms) + pingTimeout (60000ms). y debe restablecer esas opciones en el servidor y asegurarse de que la suma de pingInterval
y pingTimeout
<= 60000ms.
por ejemplo:
var socket = require('socket.io')(12345, {
pingInterval: 20000,
pingTimeout: 40000
})
Solo por curiosidad, necesito poder establecer un tiempo de espera de aproximadamente 5 minutos en mi aplicación. ¿Qué tan grave es este problema y cuánto me afectaría?
@ntomallen Si la aplicación estará en pantalla todo el tiempo, nada cambiará. Funcionará sin problemas. De lo contrario, quizás no se active al final de los 5 minutos. O lo hará de forma inesperada.
Yo uso laravel echo con React Native en las opciones del servidor de cambio de socket de Android pingTimeout
a 30000. Funciona
@sospedra gotcha. ¡Tendré que hacer algunas pruebas para asegurarme de que no sea tan malo!
¿Hay alguna razón para no usar siempre Handler.postDelayed?
alguna solución rápida para este problema? Acabo de comenzar a usar RN con Firebase.
Probé algunas soluciones de temporizador diferentes, pero no he tenido suerte para que una funcione en segundo plano (de manera consistente).
He usado un setInterval para hacer ping a mi servidor cada 10 minutos; acabo de notar este mensaje de error porque hago un setInterval(myFunction, 60000)
. ¿Es esto algo de lo que debo preocuparme?
Mi comportamiento esperado es que mientras la aplicación está abierta, puede enviar las solicitudes, pero después de suspender la aplicación (presionar el botón de inicio una vez), las solicitudes deberían dejar de dispararse. ¿Es este el comportamiento que puedo esperar? ¿Se verá afectada la duración de la batería mientras la aplicación esté suspendida?
No hay nada de qué preocuparse aquí, y la advertencia es incorrecta y debe eliminarse. No hay un "módulo de temporización" para mantenerse despierto, solo hay una devolución de llamada de Choreographer que comprueba los temporizadores en cada cuadro (lo que también hace que la granularidad mínima para los temporizadores sea de ~ 16ms).
Existe un problema de corrección en el sentido de que los temporizadores no se activan en segundo plano ni en iOS ni en Android. Sin embargo, esta advertencia parece ser específicamente sobre Android y no parece ser precisa. Todos los temporizadores deberían activarse cuando la aplicación vuelva a estar en primer plano.
¿Tiene planes de solucionar este problema pronto? El registro es molesto cada vez que estamos probando en teléfonos Android.
Recibía este error porque mi tiempo de espera era de ~ 59 minutos. El código para llamar a un método en la parte superior de la hora y tenía un setTimeout
para crear un setInterval
en la siguiente parte superior de la hora.
setTimeout
para comenzar el setInterval
en la parte superior del minuto.0
.Esta función ahora se ejecuta cada minuto en lugar de cada hora… pero como no hace nada 59 de 60 veces, parece inofensiva.
Hola @beausmith , ¿es esta realmente una solución para simplemente configurar 60 temporizadores? A mi entender, todavía mantiene el timerModule activo durante la misma hora, pero no muestra la advertencia :)
@newah - sí, es un poco hacky ... ¿puedes sugerir una mejor solución?
@beausmith , intenté usar https://github.com/ocetnik/react-native-background-timer que usa temporizadores nativos que suena como una solución; simplemente sobrescribí setTimout y setInterval con la implementación de esta lib.
La compatibilidad con temporizadores en segundo plano puede ser una ventaja o una desventaja según sus necesidades :))
Parece funcionar bien, pero no resolvió mis problemas :)
Tengo la misma advertencia si uso react-intl FormattedRelative. Porque dentro del componente FormattedRelative se usa el temporizador:
scheduleNextUpdate(props, state) {
// Cancel and pending update because we're scheduling a new update.
clearTimeout(this._timer);
const {value, units, updateInterval} = props;
const time = new Date(value).getTime();
// If the `updateInterval` is falsy, including `0` or we don't have a
// valid date, then auto updates have been turned off, so we bail and
// skip scheduling an update.
if (!updateInterval || !isFinite(time)) {
return;
}
const delta = time - state.now;
const unitDelay = getUnitDelay(units || selectUnits(delta));
const unitRemainder = Math.abs(delta % unitDelay);
// We want the largest possible timer delay which will still display
// accurate information while reducing unnecessary re-renders. The delay
// should be until the next "interesting" moment, like a tick from
// "1 minute ago" to "2 minutes ago" when the delta is 120,000ms.
const delay =
delta < 0
? Math.max(updateInterval, unitDelay - unitRemainder)
: Math.max(updateInterval, unitRemainder);
this._timer = setTimeout(() => {
this.setState({now: this.context.intl.now()});
}, delay);
}
Aquí hay un ejemplo de uso en mi código:
<FormattedRelative value={date}>
{(message: string) => <Text>{message}</Text>}
</FormattedRelative>
¿Alguien sabe cómo solucionar esta advertencia?
Esto sigue siendo un problema. Es particularmente molesto cuando se usan los servicios de firebase en Android. Por favor, arregla.
Este es un error realmente malo para los servicios de base de fuego y cuando depende de aplicaciones de terceros. Porque firebase no funciona si cambia entre aplicaciones para verificar algo para continuar el proceso.
Un ejemplo es que usamos un sistema de inicio de sesión de terceros / factor y usamos firebase para mover tokens. Pero dado que limpiamos, el token desaparece antes de que la persona vuelva a nuestra aplicación. Entonces puedo cambiar los mecanismos de limpieza, o ustedes pueden arreglar este error.
@vongohren no es que entienda completamente su caso de uso, pero una estrategia alternativa podría ser almacenar la fecha de fondo dentro de su aplicación al ingresar al fondo, luego, al regresar al primer plano, compare la fecha actual con la fecha de fondo almacenada y realice una limpieza si ha transcurrido un cierto período de tiempo ...
Para desarrollar mi caso de uso. Digamos que depende de decir que sí en otra aplicación para aceptar el inicio de sesión. Feks cambia a la aplicación de Facebook para decir que sí a una solicitud de inicio de sesión en un tercero. El ejemplo concreto con el que estoy trabajando es uPort, https://www.uport.me/. Luego, cuando confiamos en una forma de enviar mensajes a nuestra aplicación, ahora en segundo plano para decir que todo está bien, esto no funciona con firebase a menos que adoptemos su enfoque para limpiar en un momento posterior.
Supongo que estaba atascado en que la limpieza podría ocurrir justo después de la información emitida, porque entonces la información ya se había emitido y no la necesitaríamos. Pero, ¿por qué el enfoque de base de fuego no funciona en react native? Que detiene a sus trabajadores de fondo.
Necesito un tiempo de espera de 30 minutos en mi aplicación. Cada vez que el usuario interactúa con la pantalla, se restablecerá (deseche el tiempo de espera anterior, cree uno nuevo).
¿Alguna alternativa sobre cómo hacer esto de la manera correcta? ¿Es mejor manejar esto con código nativo y pasar algo a React cuando termine?
wow, esto sigue siendo un problema
@nbennink verifica la respuesta aquí . Actualmente, no hay una forma garantizada de ejecutar la tarea en segundo plano, ya que hay varios factores en juego (ahorro de batería, interacción del usuario, etc.).
También recibo la misma advertencia después de usar socket.io.
La advertencia está debajo:
Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info.
(Saw setTimeout with duration 85000ms)
Los detalles de mi paquete están a continuación:
¿Alguna solución permanente averiguarlo?
También recibo la misma advertencia después de usar socket.io.
La advertencia está debajo:
Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info.
(Saw setTimeout with duration 85000ms)
Los detalles de mi paquete están a continuación:
"reaccionar": "^ 16.3.0-alpha.1",
"react-native": "0.54.4",
"socket.io": "^ 2.1.1",
"socket.io-client": "^ 2.1.1",
¿Alguna solución permanente averiguarlo?
Ídem, ¿no hay forma de evitar esto?
Aún recibiendo esta advertencia en react-native 0.57, ¿se supone que este problema está abierto en su lugar?
¡Casi un año y React Native todavía tienen el mismo problema!
Frente al mismo problema, la misma advertencia aparece 3-4 veces. Muy molesto.
¿Existe alguna solución para solucionar este problema?
Se eliminó el mensaje de advertencia con esta solución https://stackoverflow.com/a/48778011/7427111
Básicamente, se trata de ocultar el mensaje y no solucionar el problema, supongo.
@dhavaljardosh Sí, tu conjetura es correcta.
Creé un temporizador nativo con Java y Objective C. Me funciona y oculta el mensaje. No estoy seguro de si realmente mejora el rendimiento. Como se mencionó anteriormente: todavía es malo para la batería, etc. porque hay un temporizador largo en segundo plano.
Una pregunta que debe hacerse es si realmente necesita una función de sondeo. Pensé que sí, pero luego, debido a este problema, me di cuenta de que solo necesitaba ejecutar en _alguno_ período de tiempo semi-frecuente. Así que ahora lo estoy ejecutando en el fondo de la aplicación y evitando totalmente este problema. YMMV.
mismo problema al usar Pusher ...
Probaré mi aplicación para ver cuál es el impacto en el rendimiento al configurar un temporizador cada 60 segundos.
Sin embargo, supongo que algunos de ustedes tienen experiencia con eso. ¿Puedes compartir esta experiencia, por favor? ¿Es significativo el impacto?
sigue siendo el mismo problema con la última versión.
¿alguna solución?
Yo también estoy enfrentando ese problema.
La aplicación funcionaba bien, solo cuando comencé a usar firebase llegó la advertencia.
¿Alguna solución?
Quiero entender el significado detrás de este mensaje, ya que comenzamos a recibirlo después de una función reciente que agregamos a nuestro producto. ¿El problema es _sólo_ el hecho de que el temporizador sigue funcionando mientras la aplicación está en segundo plano? ¿Sería una solución adecuada suscribirse a los eventos de estado de la aplicación y detener el temporizador si la aplicación está en segundo plano? ¿O también es problemático un temporizador de larga duración con la aplicación en el _foreground_?
Quiero entender el significado detrás de este mensaje, ya que comenzamos a recibirlo después de una función reciente que agregamos a nuestro producto. ¿El problema es _sólo_ el hecho de que el temporizador sigue funcionando mientras la aplicación está en segundo plano? ¿Sería una solución adecuada suscribirse a los eventos de estado de la aplicación y detener el temporizador si la aplicación está en segundo plano? ¿O también es problemático un temporizador de larga duración con la aplicación en el _foreground_?
Me gustaría saber esto también.
Además, ¿qué sucede con setInterval? No recibo advertencias de este, pero ¿tiene el mismo problema?
Quiero entender el significado detrás de este mensaje, ya que comenzamos a recibirlo después de una función reciente que agregamos a nuestro producto. ¿El problema es _sólo_ el hecho de que el temporizador sigue funcionando mientras la aplicación está en segundo plano? ¿Sería una solución adecuada suscribirse a los eventos de estado de la aplicación y detener el temporizador si la aplicación está en segundo plano? ¿O también es problemático un temporizador de larga duración con la aplicación en el _foreground_?
El mensaje amarillo dice "... y los temporizadores solo se pueden llamar cuando la aplicación está en primer plano".
¿El módulo del temporizador permanece activo pero los temporizadores no funcionan cuando la aplicación está en segundo plano? Entonces, ¿el problema es mantener el módulo del temporizador activo cuando una aplicación está en segundo plano? ¿Cuánto de un efecto de rendimiento / batería tendría eso? Me pregunto ...
@BerndWessels https://www.npmjs.com/package/react-native-firebase ¿Has mirado esto? Dice que permite que firebase se ejecute en el hilo nativo. No estoy seguro de cuán cierto es eso, pero podría valer la pena echarle un vistazo. Incluso podría estar usando eso, no estoy seguro.
¿Crees que si cambio a esta biblioteca tendré que cambiar mi código existente? Quiero decir, eso no sería muy agradable ...
mismo problema con Pusher en el último RN0.59, y la interfaz de usuario puede atascarse unos segundos ...
Parece que solo me encuentro con este problema cuando hago una llamada a la base de datos en tiempo real de firebase.
await firebase.database().ref('users/' + id).set(data);
RN 0.57.1
No lo he confirmado con 0.59.
@swushi Tengo el mismo problema con RN 0.59
Recibo la siguiente advertencia mientras uso la biblioteca de base de fuego
Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info. (Saw setTimeout with duration 111862ms)
Cómo deshacerse de esta advertencia ...
¿Alguien sabe cómo deshacerse de esta advertencia sin ocultarla?
Utilizo la biblioteca firebase
, no la react-native-firebase, pero parece tener el mismo problema y no sé cómo me afectará cuando llegue a producción.
Estoy muy preocupado, así que si alguien puede ayudar, por favor ...
Estoy usando el siguiente código para solucionar este problema (en este momento):
ver https://github.com/firebase/firebase-js-sdk/issues/97#issuecomment -427512040
fixtimerbug.js
/////////////////////////////////////////////////////////////////////////////
////// temporary fix to bug about 'Setting a timer' /////////////////////////
////// See: https://github.com/pusher/pusher-js/issues/248 //////////////////
////// See: https://github.com/facebook/react-native/issues/12981 ///////////
////// See: https://github.com/firebase/firebase-js-sdk/issues/97 ///////////
/////////////////////////////////////////////////////////////////////////////
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') {
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);
};
}
/////////////////////////////////////////////////////////////////////////////
@cpmech
Implementa eso en un archivo .js independiente, o lo haces dentro del script que hace la excepción del temporizador
Hola, sí, el código anterior va en un archivo llamado 'fixtimerbug.js'. Luego, lo cargo en mi App.js así:
import './src/fixtimerbug'; // <<<<<<<<<<<<<<<<<<
import React from 'react';
import { Platform, View, StatusBar } from 'react-native';
import AppNavigator from './src/navigation/AppNavigator';
import Store from './src/model/Store';
const store = new Store();
const App = () => (
<View style={{ flex: 1, backgroundColor: '#fff' }}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<AppNavigator screenProps={{ store }} />
</View>
);
export default App;
Parece que está funcionando bien, ¿qué hace exactamente?
Muchas gracias @cpmech
Hola, el código (desde aquí: https://github.com/firebase/firebase-js-sdk/issues/97#issuecomment-427512040) simplemente envuelve la función setTimeout
(global) para evitar que sea utilizado con un largo período.
En nuestra función global.setTimeout
modificada, si el tiempo de duración es mayor que el umbral MAX_TIMER_DURATION_MS
, guardamos un id
en un mapa local ( timerFix
) y luego llame a runTask
que divide el tiempo de duración en valores más pequeños. runTask
establece un tiempo de espera (usando el _setTimeout
) con los fragmentos más pequeños que se ejecutarán continuamente hasta que waitingTime
sea demasiado pequeño. Cuando waitingTime
es lo suficientemente pequeño, llamamos a React Native runAfterInteractions
para una ejecución sin problemas y, al mismo tiempo, eliminamos la entrada id
de nuestro mapa local porque ganamos En este caso, volveré a llamar a _setTimeout
. Tenga en cuenta que afterTime
se introduce en _setTimeout
para evitar que se llame con un período prolongado.
De lo contrario, en nuestra función global.setTimeout
modificada, si el tiempo de duración es menor que el umbral MAX_TIMER_DURATION_MS
, llamamos directamente al setTimeout global (guardado en _setTimeout
).
El clearTimeout
global también se ajusta para realizar un proceso de limpieza eliminando el id
del mapa local.
¡Espero eso ayude!
Enfrentando el mismo problema ... Parece que tendríamos que ocultar la advertencia por el momento. Esta es la forma más corta de hacerlo:
componentDidMount() {
console.disableYellowBox = true;
...
}
Hola, el código (de aquí: firebase / firebase-js-sdk # 97 (comentario) ) simplemente envuelve la función
setTimeout
(global) para evitar que se use durante un período prolongado.En nuestra función
global.setTimeout
modificada, si el tiempo de duración es mayor que el umbralMAX_TIMER_DURATION_MS
, guardamos unid
en un mapa local (timerFix
) y luego llame arunTask
que divide el tiempo de duración en valores más pequeños.runTask
establece un tiempo de espera (usando el_setTimeout
) con los fragmentos más pequeños que se ejecutarán continuamente hasta quewaitingTime
sea demasiado pequeño. CuandowaitingTime
es lo suficientemente pequeño, llamamos a React NativerunAfterInteractions
para una ejecución sin problemas y, al mismo tiempo, eliminamos la entradaid
de nuestro mapa local porque ganamos En este caso, volveré a llamar a_setTimeout
. Tenga en cuenta queafterTime
se introduce en_setTimeout
para evitar que se llame con un período prolongado.De lo contrario, en nuestra función
global.setTimeout
modificada, si el tiempo de duración es menor que el umbralMAX_TIMER_DURATION_MS
, llamamos directamente al setTimeout global (guardado en_setTimeout
).El
clearTimeout
global también se ajusta para realizar un proceso de limpieza eliminando elid
del mapa local.¡Espero eso ayude!
Muchas gracias! Trabajado como un encanto.
Hola, el código (de aquí: firebase / firebase-js-sdk # 97 (comentario) ) simplemente envuelve la función
setTimeout
(global) para evitar que se use durante un período prolongado.En nuestra función
global.setTimeout
modificada, si el tiempo de duración es mayor que el umbralMAX_TIMER_DURATION_MS
, guardamos unid
en un mapa local (timerFix
) y luego llame arunTask
que divide el tiempo de duración en valores más pequeños.runTask
establece un tiempo de espera (usando el_setTimeout
) con los fragmentos más pequeños que se ejecutarán continuamente hasta quewaitingTime
sea demasiado pequeño. CuandowaitingTime
es lo suficientemente pequeño, llamamos a React NativerunAfterInteractions
para una ejecución sin problemas y, al mismo tiempo, eliminamos la entradaid
de nuestro mapa local porque ganamos En este caso, volveré a llamar a_setTimeout
. Tenga en cuenta queafterTime
se introduce en_setTimeout
para evitar que se llame con un período prolongado.De lo contrario, en nuestra función
global.setTimeout
modificada, si el tiempo de duración es menor que el umbralMAX_TIMER_DURATION_MS
, llamamos directamente al setTimeout global (guardado en_setTimeout
).El
clearTimeout
global también se ajusta para realizar un proceso de limpieza eliminando elid
del mapa local.¡Espero eso ayude!
¿Esto realmente soluciona el problema o simplemente elimina la advertencia?
Hola, el código (de aquí: firebase / firebase-js-sdk # 97 (comentario) ) simplemente envuelve la función
setTimeout
(global) para evitar que se use durante un período prolongado.En nuestra función
global.setTimeout
modificada, si el tiempo de duración es mayor que el umbralMAX_TIMER_DURATION_MS
, guardamos unid
en un mapa local (timerFix
) y luego llame arunTask
que divide el tiempo de duración en valores más pequeños.runTask
establece un tiempo de espera (usando el_setTimeout
) con los fragmentos más pequeños que se ejecutarán continuamente hasta quewaitingTime
sea demasiado pequeño. CuandowaitingTime
es lo suficientemente pequeño, llamamos a React NativerunAfterInteractions
para una ejecución sin problemas y, al mismo tiempo, eliminamos la entradaid
de nuestro mapa local porque ganamos En este caso, volveré a llamar a_setTimeout
. Tenga en cuenta queafterTime
se introduce en_setTimeout
para evitar que se llame con un período prolongado.De lo contrario, en nuestra función
global.setTimeout
modificada, si el tiempo de duración es menor que el umbralMAX_TIMER_DURATION_MS
, llamamos directamente al setTimeout global (guardado en_setTimeout
).El
clearTimeout
global también se ajusta para realizar un proceso de limpieza eliminando elid
del mapa local.¡Espero eso ayude!
¡Muchas gracias! No afectará el rendimiento general de la aplicación, ¿verdad?
Hola, el código (de aquí: firebase / firebase-js-sdk # 97 (comentario) ) simplemente envuelve la función
setTimeout
(global) para evitar que se use durante un período prolongado.
En nuestra funciónglobal.setTimeout
modificada, si el tiempo de duración es mayor que el umbralMAX_TIMER_DURATION_MS
, guardamos unid
en un mapa local (timerFix
) y luego llame arunTask
que divide el tiempo de duración en valores más pequeños.runTask
establece un tiempo de espera (usando el_setTimeout
) con los fragmentos más pequeños que se ejecutarán continuamente hasta quewaitingTime
sea demasiado pequeño. CuandowaitingTime
es lo suficientemente pequeño, llamamos a React NativerunAfterInteractions
para una ejecución sin problemas y, al mismo tiempo, eliminamos la entradaid
de nuestro mapa local porque ganamos En este caso, volveré a llamar a_setTimeout
. Tenga en cuenta queafterTime
se introduce en_setTimeout
para evitar que se llame con un período prolongado.
De lo contrario, en nuestra funciónglobal.setTimeout
modificada, si el tiempo de duración es menor que el umbralMAX_TIMER_DURATION_MS
, llamamos directamente al setTimeout global (guardado en_setTimeout
).
ElclearTimeout
global también se ajusta para realizar un proceso de limpieza eliminando elid
del mapa local.
¡Espero eso ayude!¿Esto realmente soluciona el problema o simplemente elimina la advertencia?
No, no aborda el problema. Es un buen trabajo.
Hola, el código (de aquí: firebase / firebase-js-sdk # 97 (comentario) ) simplemente envuelve la función
setTimeout
(global) para evitar que se use durante un período prolongado.
En nuestra funciónglobal.setTimeout
modificada, si el tiempo de duración es mayor que el umbralMAX_TIMER_DURATION_MS
, guardamos unid
en un mapa local (timerFix
) y luego llame arunTask
que divide el tiempo de duración en valores más pequeños.runTask
establece un tiempo de espera (usando el_setTimeout
) con los fragmentos más pequeños que se ejecutarán continuamente hasta quewaitingTime
sea demasiado pequeño. CuandowaitingTime
es lo suficientemente pequeño, llamamos a React NativerunAfterInteractions
para una ejecución sin problemas y, al mismo tiempo, eliminamos la entradaid
de nuestro mapa local porque ganamos En este caso, volveré a llamar a_setTimeout
. Tenga en cuenta queafterTime
se introduce en_setTimeout
para evitar que se llame con un período prolongado.
De lo contrario, en nuestra funciónglobal.setTimeout
modificada, si el tiempo de duración es menor que el umbralMAX_TIMER_DURATION_MS
, llamamos directamente al setTimeout global (guardado en_setTimeout
).
ElclearTimeout
global también se ajusta para realizar un proceso de limpieza eliminando elid
del mapa local.
¡Espero eso ayude!¡Muchas gracias! No afectará el rendimiento general de la aplicación, ¿verdad?
No, no afecta el rendimiento en absoluto.
Una nota rápida sobre
Si le molesta, simplemente agregue console.ignoredYellowBox = ['Configurando un temporizador'];
y
Enfrentando el mismo problema ... Parece que tendríamos que ocultar la advertencia por el momento. Esta es la forma más corta de hacerlo:
componentDidMount () {console.disableYellowBox = true; ...}
Ésta no es una solución viable. Los errores aún ocurren, simplemente no recibe una notificación.
¿Resultado? El error de análisis aún debe ocurrir.
En el caso de utilizar escuchas de Firebase, por ejemplo, estará ocultando una gran cantidad de errores, pero su entorno de desarrollo seguirá manejándolos.
Caso en cuestión: mi proyecto basado en expo seguía fallando porque intentaba mapear cada error del temporizador.
Estoy cerrando esto porque no creo que React Native agregue soporte para AlarmManager en el núcleo. Se puede hacer con módulos de terceros o código nativo personalizado.
¿ La solución de
Hola, creo que encontré la solución:
En primer lugar, debe encontrar el siguiente archivo en su proyecto: bibliotecas / Core / Timers / JSTimer; js
Ábralo y solo tiene que cambiar esta constante MAX_TIMER_DURATION_MS, para aumentar por encima de su duración, ¡escribió al final de la advertencia!
aumentar el temporizador, pero ¿cuánto?
@dulmandakh, ¿hay algún proyecto de código abierto que resuelva este problema que conozca?
@dulmandakh, ¿hay algún proyecto de código abierto que resuelva este problema que conozca?
¿RNFirebase tal vez? @dulmandakh
Puede reprogramar el temporizador con un tiempo fijo hasta que expire:
const setLogoutTimer = expirationTime => {
return dispatch => {
timer = setTimeout(() => {
if (expirationTime>60000)
{
console.log(`set new exp:${expirationTime-60000}`);
dispatch(setLogoutTimer(expirationTime-60000));
}
else
{
console.log('logout');
dispatch(logout());
}
}, 60000);
};
};
Han pasado 2 años para que los nativos de reacción o firebase solucionen este problema correctamente. :(
bien, después de unas horas de larga investigación, todo lo que quiero saber es si causé el problema de alguna manera.
No estoy seguro de cuándo apareció.
¿Aparece tan pronto como llamo a Firestore?
No estoy usando ningún temporizador en mi aplicación
@luismasg No uso setTimeout en mi código, ya que es una mala práctica, pero conozco la fuente del error y no puedo detenerlo y parece que proviene de establecer una conexión remota con mi base de datos, aparentemente la biblioteca que estoy usando establece el tiempo de espera para mantener vivo el TTL, verifique su biblioteca de dependencias y vea si puede identificar el que causa el problema
Honestamente, de todos modos, no creo que usar temporizadores / intervalos JS sea una buena idea para los temporizadores largos, la advertencia está ahí por una razón.
En su lugar, use eventos de ciclo de vida para agregar / eliminar temporizadores cortos. Si necesita una ejecución real en segundo plano, use código nativo con servicios en primer plano (Android) y tareas en segundo plano (iOS).
Honestamente, de todos modos, no creo que usar temporizadores / intervalos JS sea una buena idea para los temporizadores largos, la advertencia está ahí por una razón.
Como se mencionó ampliamente anteriormente, muchas personas luchan con bibliotecas que usan temporizadores más largos. "No uses firebase" no es una solución.
Obviamente, este es un problema que se encuentra a menudo, manejarlo mejoraría la experiencia del desarrollador de react-native
que parece que es el objetivo final ...
Yo no diría que "no usar firebase" es la respuesta, más bien "arreglar firebase para no usar temporizadores largos y usar los bloques de construcción nativos apropiados para la tarea w / e para la que están usando temporizadores largos".
Pero tiene razón, sería ideal que RN admita temporizadores largos de alguna manera, pero considerando todas las advertencias que existen (como un mayor consumo de batería, tiempo de ejecución innecesario en segundo plano, etc.), solo hará que los desarrolladores se disparen a sí mismos. En todo caso, debería ser una primitiva de temporizador / intervalo separada.
En todo caso, debería ser una primitiva de temporizador / intervalo separada.
Mi comprensión de de qué se trata este problema es la falta de un elemento tan primitivo 😄
usa el temporizador dentro del temporizador, ¡eso es todo!
@dulmandakh ¿
Agregué esto a App.js, y esto lo solucionó (temporal hasta que haya una solución oficial)
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.startWith("_lt_")) {
_clearTimeout(timerFix[id]);
delete timerFix[id];
return;
}
_clearTimeout(id);
};
}
Esta es una solución alternativa, no una solución.
Agregué esto a App.js, y esto lo solucionó (temporal hasta que haya una solución oficial)
... if (typeof id === "string" && id.startWith("_lt_")) { ...
'startWith' debería ser 'startsWith' si vas a usar ese código.
Estoy experimentando esto con AWS Amplify Datastore. En lugar de una solución adecuada, deshabilito la advertencia con
import { YellowBox } from 'react-native';
YellowBox.ignoreWarnings(['Setting a timer']);
No tengo claro si el problema subyacente es algo que RN necesita solucionar, Amplify necesita solucionar o es algo que necesito parchear. Obviamente, no quiero problemas de rendimiento.
Si le molesta, solo agregue
console.ignoredYellowBox = ['Setting a timer'];
¿Dónde debo agregar esto? Lo intenté en el archivo de pantalla y el archivo de acción, pero aún no funciona
Simplemente colóquelo en algún lugar de su archivo App.js. Lo puse en mi constructor por ejemplo.
No sé si ese es el mejor lugar, así que si alguien sabe algo mejor, ¡me gustaría escucharlo!
Creo que quien esté usando Firebase puede resolver este problema configurando la persistencia de la aplicación después de (iniciar sesión / registrarse)
* después de crear un nuevo usuario, iniciará sesión automáticamente
https://firebase.google.com/docs/auth/web/auth-state-persistence
entonces ... después de la autenticación de un usuario, se crea una variable de tiempo.
el valor predeterminado para firebase es local
. "firebase.auth.Auth.Persistence.LOCAL"
puedes cambiar usando:
firebase.auth.Auth.Persistence.SESSION
firebase.auth.Auth.Persistence.NONE
o usando un localStorage ...
Hasta que lo resuelvan de manera definitiva ...
importar {YellowBox} desde "react-native";
importar _ de "lodash";
YellowBox.ignoreWarnings (["Configuración de un temporizador"]);
const _console = _.clone (consola);
console.warn = (mensaje) => {
if (message.indexOf ("Configuración de un temporizador") <= -1) {
_console.warn (mensaje);
}
};
Una vez resuelto, el código basura se elimina y ¡listo!
Esto se puede solucionar con RxJS.
Básicamente divide su temporizador 5200
en temporizadores 5 * 1000 + 200
.
import { of, range } from 'rxjs';
import {
concatMap,
delay,
filter,
mapTo,
switchMap,
tap,
} from 'rxjs/operators';
// ~ setTimeout(..., 5200);
const source = of(5200).pipe(
switchMap(duration => {
const times = Math.floor(duration / 1000); // = 5
const remainder = duration % 1000; // = 200
return range(1, times).pipe(
concatMap(i => of(i).pipe(delay(1000))),
tap(console.log),
filter(i => i === times),
delay(remainder),
tap(console.log),
mapTo('Done !'),
);
}),
);
source.subscribe(console.log);
1 // After 1s
2 // After 2s
3 // After 3s
4 // After 4s
5 // After 5s
5 // After 5s + 200 ms
'Done !'
Creo que quien esté usando Firebase puede resolver este problema configurando la persistencia de la aplicación después de (iniciar sesión / registrarse)
* después de crear un nuevo usuario, iniciará sesión automáticamente
https://firebase.google.com/docs/auth/web/auth-state-persistence
entonces ... después de la autenticación de un usuario, se crea una variable de tiempo.
el valor predeterminado para firebase es
local
. "firebase.auth.Auth.Persistence.LOCAL"puedes cambiar usando:
firebase.auth.Auth.Persistence.SESSION
firebase.auth.Auth.Persistence.NONE
o usando un localStorage ...
¡Excelente! Sin embargo, ¿qué tal para Firestore?
Creo que quien esté usando Firebase puede resolver este problema configurando la persistencia de la aplicación después de (iniciar sesión / registrarse)
* después de crear un nuevo usuario, iniciará sesión automáticamente
https://firebase.google.com/docs/auth/web/auth-state-persistence
entonces ... después de la autenticación de un usuario, se crea una variable de tiempo.
el valor predeterminado para firebase eslocal
. "firebase.auth.Auth.Persistence.LOCAL"
puedes cambiar usando:
firebase.auth.Auth.Persistence.SESSION
firebase.auth.Auth.Persistence.NONE
o usando un localStorage ...¡Excelente! Sin embargo, ¿qué tal para Firestore?
si está utilizando el SDK de firebase anterior, migre al SDK de administrador de firestore.
la mayoría de los problemas se resolverán
Todavía nadie puede resolver este problema. # la vergüenza de los desarrolladores; p
Todavía nadie puede resolver este problema. # la vergüenza de los desarrolladores; p
Nunca avergüence a los contribuyentes de código abierto. Es una pena que esto no se haya solucionado, pero la fuente está abierta, si sabe cómo resolverlo, estoy seguro de que agradecerían una solicitud de extracción.
Dicho esto, ¿por qué diablos está cerrado este problema ?
Porque debería arreglarse en las bibliotecas infractoras. Y las bibliotecas infractoras no ven ningún problema con la forma en que se ha implementado.
Entonces nadie lo arreglará porque ambas partes no creen que esté roto.
Pueden avergonzarse un poco por esto 😄
Chicos, creo que esto no se ha "resuelto" por la sencilla razón de que es una muy mala idea usar temporizadores largos.
Si desea ejecutar temporizadores en segundo plano / eventos en el futuro, necesitará una biblioteca nativa para hacerlo. Esto también es especialmente difícil en ambas plataformas debido a las limitaciones de ejecución en segundo plano.
Basándonos en el comentario de @eightyfive , hicimos un reemplazo directo para las funciones rxjs6 delay
, timeout
& interval
.
Aún queda una pregunta, ¿alguien puede explicar si el "módulo de temporizador" permanece bloqueado cuando se utilizan intervalos más pequeños? Básicamente, solo hace que el temporizador se detenga cuando la aplicación no está en primer plano. ¿O esto solo oculta el problema?
import { switchMap, concatMap, delay as nativeDelay, mapTo, filter, switchMapTo, repeat } from 'rxjs/operators'
import { range, of, race, throwError, TimeoutError } from 'rxjs'
const TIMER_INTERVAL = 1000
const reactNativeTimer = (duration) => {
const times = Math.floor(duration / TIMER_INTERVAL)
const remainder = duration % TIMER_INTERVAL
if (times < 1) {
return of(true).pipe(nativeDelay(remainder))
}
return range(1, times).pipe(
concatMap(i => of(i).pipe(nativeDelay(TIMER_INTERVAL))),
filter(i => i === times),
nativeDelay(remainder)
)
}
/**
* React Native compatible version of delay pipe
* <strong i="11">@param</strong> {number} duration in ms
*/
export const delay = (duration) => {
return (source) => {
return source.pipe(
switchMap(next =>
reactNativeTimer(duration).pipe(mapTo(next))
)
)
}
}
/**
* React Native compatible version of timeout pipe
* <strong i="12">@param</strong> {number} duration in ms
*/
export const timeout = (duration) => {
return (source) => {
const timeoutTimer = reactNativeTimer(duration).pipe(
switchMapTo(throwError(new TimeoutError()))
)
return race(source, timeoutTimer)
}
}
/**
* React Native compatible version of interval
* <strong i="13">@param</strong> {number} duration in ms
*/
export const interval = (duration) => {
return reactNativeTimer(duration).pipe(
repeat()
)
}
Lo curioso es que todos en este hilo están discutiendo una solución para ignorar esta advertencia.
Cuando fui redirigido a este "problema" desde la advertencia, esperaba encontrar la documentación adecuada, explicando "¿cómo?" para manejarlo y un poco más de razonamiento sobre "¿por qué?".
A este #millenial le gustaría señalar que:
react-native
Dicho esto , señalaré nuevamente que este problema no debe cerrarse, está marcado como known-issue
y Help Wanted
.
Respuestas millenial a millenial :)
Este error no requiere documentación, se explica por sí mismo: configura un temporizador largo.
Dicho esto, volveré a señalar que este problema no debe cerrarse, está marcado como problema conocido y se necesita ayuda.
Completamente de acuerdo. Ahorrará tiempo a muchas personas que vengan de la URL de referencia en la advertencia.
Para usuarios de firebase / firestore: simplemente volví a usar los puntos finales REST directamente para las llamadas de firestore. Como solo necesitaba auth y firestore, eso resolvió mis problemas con bastante facilidad. Fragmento aquí:
Lo hice dentro de la aplicación () de la siguiente manera:
importar {YellowBox} desde 'react-native';
exportar aplicación de función predeterminada () {
YellowBox.ignoreWarnings (['Configuración de un temporizador']);
...
...
..
}
Recordar
Lo que hice y está funcionando conmigo, pero aún no sé si es una buena práctica o no
Navegado al archivo
node_modulesreact-native \ Libraries \ Core \ TimersJSTimers.js
hay una función const MAX_TIMER_DURATION_MS = 60 * 1000
y aumenté el tiempo a 60 * 100000 y dejó de aparecer
Hola,
Este problema tiene aproximadamente 3 años y todavía tenemos esta advertencia;)
como dijo @RWOverdijk ignorar la advertencia no es una solución.
¿Existe ya una solución que me perdí?
Gracias <3
Hola a todos, estamos decidiendo bloquear este problema. Sé que este problema es frustrante para muchos de ustedes y quiero tomarme el tiempo para ayudarlos a comprender por qué estamos tomando esta decisión.
React Native tiene una implementación personalizada de temporizadores JS como setTimeout
. En Android, la forma en que funciona es que los temporizadores JS se rastrean en el lado nativo, y el lado nativo decide cuándo activar estos temporizadores. Esto permite que React Native sea más inteligente acerca de cuándo se activan los temporizadores y, en particular, cómo se relacionan con el ciclo de vida y la representación de la aplicación.
Aquí está mi entendimiento, después de leer el código y probarlo un poco:
Creo que esto es principalmente una cuestión de corrección y menos de rendimiento. El problema es que no puede confiar en los temporizadores largos si el usuario hace un fondo de su aplicación.
Si no le importa que su temporizador se active más tarde cuando la aplicación vuelva a estar en primer plano, creo que ignorar la advertencia de YellowBox es una buena idea.
Por otro lado, si su temporizador espera ser llamado durante la vida útil de una sesión, y no debería activarse nuevamente en primer plano, deberá hacer algo para asegurarse de que el temporizador se ignore en primer plano.
No conozco los detalles de estas bibliotecas de terceros. En última instancia, se reduce a la pregunta anterior. Si estas bibliotecas de terceros tienen problemas relacionados con la resolución de temporizadores en primer plano, deberá encontrar una manera de solucionarlo. Algunos comentarios anteriores proponen formas de hacer esto para Firebase, por ejemplo. Sin embargo, en última instancia, es posible que se sienta mejor si confía en una biblioteca desarrollada específicamente con React Native en mente.
Por otro lado, si la biblioteca de terceros no tiene problemas con los temporizadores que se resuelven en primer plano, puede ignorar el error.
setTimeout
pasar por AlarmManager
, como se sugirió inicialmente?AlarmManager
activará la aplicación si está en segundo plano, y no creemos que temporizadores como setTimeout
deban activar la aplicación. La mayoría de estos temporizadores prolongados están configurados para cosas como tiempos de espera, y solo son relevantes mientras la aplicación está abierta. Despertar una aplicación en segundo plano es costoso y solo debe hacerse si el desarrollador tiene esta intención explícitamente.
Al mismo tiempo, es probable que muchas personas necesiten algo como esto. Podríamos desarrollar una API que no pase por setTimeout
. Pero debido al esfuerzo de Lean Core en este momento, en realidad estamos tratando de evitar aumentar la superficie de API para React Native. Creemos que esta es una tarea mejor manejada por una biblioteca de terceros como react-native-background-timer
.
Queremos que los desarrolladores estén al tanto de lo que sucede. Si alguien instala una biblioteca que depende de la exactitud de setTimeout
, creemos que el desarrollador debe tener en cuenta que no podemos garantizar esta exactitud. Queremos dejar que los desarrolladores individuales tomen la decisión de si esta advertencia es importante en su caso de uso particular.
Comentario más útil
@ skv-headless Opinión entrante. :)
En mi opinión, esa actitud hacia los problemas debe desaparecer. Lo he visto aparecer con más frecuencia y hace que la gente ignore las advertencias. Son advertencias. Te advierten. No los ignore, haga algo. He visto aplicaciones en las que se ignoran todas las advertencias, incluso los avisos de desaprobación. Luego, su aplicación se rompe y se pregunta por qué.
En este caso, puede configurar estos tiempos de espera y reducirlos, o configurar un enfoque diferente para tratar con ellos. Tal vez incluso moleste a los encargados de las bibliotecas y pídales que le ayuden a encontrar una solución.
Mi consejo es seguir este hilo hasta que alguien inteligente encuentre una solución real, para que luego pueda informarse con esa respuesta. Y luego, tal vez, mientras tanto (si no puede o no quiere abordar el problema) ignore las advertencias.
TL; DR;
Sí, puede ignorar las advertencias temporalmente. Simplemente verifique de vez en cuando para ver cuál es el estado y si se requiere alguna acción.