React-native: 在计时中添加对AlarmManager的支持,以允许正确处理长计时器

创建于 2017-03-16  ·  173评论  ·  资料来源: facebook/react-native

在Android上的React Native中无法正确设置多个分钟的计时器:它会使Timing模块保持唤醒状态,而不是依赖系统在计时器关闭时唤醒我们。

我们应该探索设置一个截止点,将其委托给AlarmManager和Handler.postDelayed,而不是使用framecallbacks处理计时器。

Bug JavaScript Android

最有用的评论

@ skv-headless意见传入。 :)

我认为对问题的态度必须消失。 我一直看到它弹出的频率更高,并且导致人们忽略警告。 他们是警告。 他们警告您。 不要忽略他们,做点什么。 我见过的应用程序会忽略所有警告,甚至弃用通知。 然后您的应用程序中断了,您就想知道为什么。

在这种情况下,您可以配置这些超时并降低它们,或设置其他处理它们的方法。 甚至可能会戳图书馆的维护者,并要求他们提供解决方案。

我的建议是,遵循这个思路,直到有聪明的人提出实际的解决方案为止,这样您就可以用这个答案来教育自己。 然后,也许在此期间(如果您不能/不想解决问题)忽略警告。

TL; DR;

是的,您可以暂时忽略警告。 只需不时检查一下状态,看看是否需要采取任何措施。

所有173条评论

很大的进步!

这将对socket.io有所帮助,默认情况下,该定时器保持85000ms的定时器不变。 在RN主节点上,阈值为60000ms

而Firebase也使用长计时器。

使用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 111862ms)

如何摆脱这个警告...

我也在使用firebase库时收到以下警告。 有人知道如何解决这个问题吗?

我也收到与firebase此警告。

"firebase": "^3.9.0",
"react-native": "0.44.0"

同一期( 85000ms ),但没有firebase 。 我的包裹清单:

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

我在Android上使用0.44.0遇到类似的问题。 我也没有使用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)

嗨,大家好..我想知道是否对此有任何快速的解决方法。 我正在使用:

react-native 0.44 react 16.0.0-alpha.6 feathers-socketio 1.6.0

在开发过程中,它非常烦人。.现在仍然可以隐藏警告吗?

与firebase 3.9.0相同的问题

如果麻烦,您只需添加console.ignoredYellowBox = ['Setting a timer'];

@ skv-headless意见传入。 :)

我认为对问题的态度必须消失。 我一直看到它弹出的频率更高,并且导致人们忽略警告。 他们是警告。 他们警告您。 不要忽略他们,做点什么。 我见过的应用程序会忽略所有警告,甚至弃用通知。 然后您的应用程序中断了,您就想知道为什么。

在这种情况下,您可以配置这些超时并降低它们,或设置其他处理它们的方法。 甚至可能会戳图书馆的维护者,并要求他们提供解决方案。

我的建议是,遵循这个思路,直到有聪明的人提出实际的解决方案为止,这样您就可以用这个答案来教育自己。 然后,也许在此期间(如果您不能/不想解决问题)忽略警告。

TL; DR;

是的,您可以暂时忽略警告。 只需不时检查一下状态,看看是否需要采取任何措施。

@imamatory我认为是Rectotron提供的

我想是Rectotron制作的

如果是这样,则可以简单地忽略此警告。
...但是有时候我的android模拟器变慢,也许这是原因之一。

@imamatory我希望真正的解决方案也一样简单

嗨,我想我找到了解决方案:
首先,您必须在项目中找到以下文件:libraries / Core / Timers / JSTimer; js
打开它,您只需要更改此常量MAX_TIMER_DURATION_MS,以增加您的持续时间,在警告结尾处写道!

@nicolasZZ您好,感谢您的解决方案。 但这是修改JSTimer库而不是我们自己的代码的好习惯吗?

@nicolasZZ @AmroAly在我看来,此解决方案不是很好的做法,因为它非常不稳定,最好是在发布正式解决方案时忽略警报。

console.ignoredYellowBox = [
    'Setting a timer'
]

@ skv-headless的解决方案很好,但在我的情况下,只能在括号之间输入“ enter”

@rigobcastro谢谢,隐藏了烦人的警报。

@ DZuz14如果您可以发送公关或至少开始对话,那就

嗨〜
我使用了socket.io。 nodejs and RN44 or RN 45
我看到警告此计时器。

我找到了这个解决方案
reference reactotron PR

个人服务器nodejs和scoket.io

const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server, {pingTimeout: 30000})

谢谢!

我有一个用于Android的简单react native项目,并且正在使用firebase auth和react native用于Login和Signup,但是出现了黄色错误,我该怎么办? 我的问题在stackoverslow中的链接(https://stackoverflow.com/questions/44603362/setting-a-timer-for-a-long-period-of-time-ie-multiple-minutes)

谢谢@ DZuz14
运行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.

我想使用firebase auth和React Native进行登录和注册,但出现了黄色错误,
1:这个模块到底是什么?
2:为什么我的项目需要此模块?

我通过以下链接询问了stackoverflow :(https://stackoverflow.com/questions/44603362/setting-a-timer-for-a-long-period-of-time-ie-multiple-minutes)
我通过以下链接向Google Firebase团队报告:(https://github.com/firebase/firebase-js-sdk/issues/97)

@ DZuz14我有和@saeedhei相同的问题。

基本上,我们使用的是firebase节点模块,该模块使用这些长时间计时器。

我想添加模块还不够,我们实际上必须重写firebase节点模块中的代码才能使用Alarms而不是Javascript计时器,对吗?

谢谢@ DZuz14

因此,如果查看名为firebase的npm包,您会发现它在很多地方都使用setTimeout。 可以,因为该库是为网站和node.js服务器编写的。 react-native是一种node.js服务器,但它可以在电话上运行-正如警告正确指出的那样-长时间运行的Javascript计时器在此环境中效果不好,可能会耗尽电池电量并产生其他不良副作用。

因此,我想我们必须说服Firebase的人改变您的方法,并分发一个专门为react-native制造的软件包。

@BerndWessels https://www.npmjs.com/package/react-native-firebase你看过吗? 说它允许firebase在本机线程上运行。 不确定这是多么真实,但可能值得一看。 我不确定,您甚至可能正在使用它。

@ DZuz14谢谢,我会检查一下。

console.ignoredYellowBox = [
“设置计时器”
]

@rigobcastro我在哪里可以输入或粘贴此代码?

@ Jazz747在设置文件的顶部,例如app.js,index.android.js或index.ios.js

console.ignoredYellowBox = [ 'Setting a timer' ]
此代码仅将警告隐藏在react native内部。

浏览器控制台内的警告如何?

有谁知道RN团队或社区中的某人正在努力解决此问题?

警告弹出窗口重定向到此问题,但是除了隐藏警告之外,我在这里找不到任何合适的解决方案,这根本不是解决方案。 有什么想法或建议吗?

@SuhairZain一切似乎都表明RN是外部库的错误

@rigobcastro使用setInterval()调用可以很容易地重现此警告,该调用的时间足够长(在我的情况下为5分钟)。 因此,我想这不是由第三方库引起的。

顺便说一句,此后我在这里找到了一个库: react-native-background-timer ,它可以帮助我完成工作。

@SuhairZain是的,你是对的! 我的问题出在3rd party lib上,但是所有者修复了错误(我想他们只是更改了一些setInterval() ),警告消失了。

很好的推荐,谢谢。

我在这里有同样的问题。 而且仍然无法理解我应该如何处理这个问题。

rn:0.45.1
火力:4.1.3

亲爱的@escalepion我向

@escalepion如果您的问题与设置长时间运行的计时器有关,请查看上面的我的评论,看看它是否对您有帮助。

@SuhairZain对不起,我无法理解如何使用setInterval或react-native-background-timer :(我在哪里以及如何编写代码?您有例子吗?

有谁知道如何找出哪个图书馆造成了危害? 我最近将RN升级到0.46,突然出现了此错误。 我的项目中有很多图书馆,我只能想到逐个研究它们,这显然不理想。

干杯!

@ abeltje1 ,如果您知道如何解决此问题,请在这里更新

我肯定会喜欢@liketurbo

我遇到此问题以及redux-saga每30分钟重新验证一次API令牌。

因此,在这种情况下,等待这么长时间实际上是正确的。 我想还有其他需要长时间等待的情况。

然后我的问题是,为什么这是警告? 有什么可以打破/发生的? 我不应该能够使用任何LLT(长期交易)吗?

如果LLT没问题。 解决此问题的最佳方法是什么? 延长AlarmManager时间?

提前致谢 ;)

我遇到与@sospedra相同的问题。 我正在使用redux-saga并且有一个传奇,每隔3分钟就会在后台刷新应用程序中的某些数据,因此传奇包含代码yield call(delay, 3 * 60000); 。 结果,我收到此“设置计时器很长的时间...”错误。

我也想知道对于这种事情建议的方法是什么。 如果仅以这种方式工作,我会遇到什么问题。 该错误消息表示可能存在性能问题,并且如果应用程序在后台运行,则计时器实际上不会在正确的时间触发?

如果此代码设置3分钟计时器可能会出现问题,那么哪种替代解决方案可以实现相同的功能而不会遇到这些问题?

仍然遇到同样的问题。

我认为,唯一的解决方案是转向本机Android开发

问题仍然无法解决? 有人找到解决方案了吗?

使用Firebase时出现警告。

如果问题不是来自第三方库,而是您自己设置了长时间超时,那么一个好的解决方案是使用react-native-background-timer库。 它的自述文件也包含一个简单的示例。

不幸的是,如果问题出自第三方库,那么除了找到setTimeout的调用位置并提出问题/提交PR以使用上述库外https://github.com/facebook/react-native/issues/12981#issuecomment -331074444并尝试是否适合您。

也请在android上增加超时时间。

正如@SuhairZain所说, react-native-background-timer是一个很好的解决方法。 这可以清除警告消息

使用socket.io时收到此警告

因为socket.io具有85ms的计时器

FWIW这只发生在我在开发过程中使用Reactotron时...

我不得不承认,让我疯狂了一段时间,但我知道我不能忽略这个信息

我不再从事与这个问题有关的项目,因此我无法真正测试这种方法是否有效,但至少在理论上应该如此。 如果错误是由使用setTimeout或setInterval的第三方模块引起的,并且延迟很长,那么这应该可以解决您的问题。 它的工作是对全局setTimeout和setInterval进行猴子修补,以使用react-native-background-timer代替:

import BackgroundTimer from 'react-native-background-timer';

setTimeout = BackgroundTimer.setTimeout;
setInterval = BackgroundTimer.setInterval;
clearTimeout = BackgroundTimer.clearTimeout;
clearInterval = BackgroundTimer.clearInterval;

将此代码编写在早期初始化的某个位置,最好是尽早在index.android.js或index.ios.js中编写。 如果有人可以对此进行测试,将不胜感激。

@SuhairZain :到目前为止,您的建议对我有所帮助,但有一些调整:

setTimeout = BackgroundTimer.setTimeout.bind(BackgroundTimer)
setInterval = BackgroundTimer.setInterval.bind(BackgroundTimer)
clearTimeout = BackgroundTimer.clearTimeout.bind(BackgroundTimer)
clearInterval = BackgroundTimer.clearInterval.bind(BackgroundTimer)

@levity我将您的代码添加到我的app.js中,但是我明白了

未定义不是对象(评估'RNBackgroundTimer.setTimeout')

@realtebo听起来像您可能没有运行它们的自述文件中描述的react-native-background-timer的安装,方法是运行react-native link或使用CocoaPods。

@levity :您是说运行react-native link吗?

npm install -g react-native-cli
反应本机链接
在C:\ Users \ realtebo \ Downloads \ manager2 \ node_modules中扫描文件夹中的符号链接(54ms)
react-native link不能在Create React Native App项目中使用。 如果您需要包括一个依赖于自定义本机代码的库,则可能必须先退出。 有关更多信息,请参见https://github.com/react-community/create-react-native-app/blob/master/EJECTING.md

我不想弹出...,所以,..我该怎么办?

哦,对不起,我不知道如何为您创建Create Native Native App项目提供帮助。 我自己从来没有用过。

嗨,您好,
我在react-native: ^0.49.3遇到了一些问题...

cf. https://github.com/ocetnik/react-native-background-timer/issues/65

希望您能有所帮助,谢谢您的时间;)

嗨,我遇到了相同的问题,我正在使用0.49 ,执行此操作后

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

上面是redux中的Action ,它也使用redux-thunk .。单击按钮将表单中的数据保存到firebase ,保存成功后将调度saveDataSuccess() ,然后导航到下一个标签。
现在,我怀疑问题似乎在这里const userId = firebase.auth().currentUser.uid但我不确定。 这是问题的屏幕快照。 (该应用程序运行正常,但出现此警告,我不知道是否应该忽略它),或者我在这里做错了事,需要您的帮助,thanx

warning

warning2

嘿,警告是关于setTimeout的,您正在组件中使用它吗?
是的,这行const userId = firebase.auth()。currentUser.uid; 不能正常工作,这是一个承诺,当您使用userId时,它仍然无法发送。
更好的方法是从actionCreator获取userId,您已经在发送userInfo变量,请尝试以下操作:

我将假设userInfo来自firebase auth登录,因此您具有uid

导出函数saveUserData(userInfo){
返回(发送)=> {
dispatch(saveDataRequest())
// const userId = firebase.auth()。currentUser.uid;
返回firebase.database()。ref('users /'+ userInfo.uid).set(userInfo)
.then(()=> {
dispatch(saveDataSuccess());
dispatch(NavigationActions.navigate({routeName:'TabContactNavigation'}))
})
.catch((错误)=> {
调度(saveDataFailure(错误))
});
}
}
我希望这会有所帮助,对不起我的英语不好= P

布里斯

El 23/10/2017,las 23:59,Yasir [email protected]ó

嗨,我遇到了与我使用0.49相同的问题,它在执行此操作后出现

导出函数saveUserData(userInfo){
返回(发送)=> {
dispatch(saveDataRequest())
const userId = firebase.auth()。currentUser.uid;
返回firebase.database()。ref('users /'+ userId).set(userInfo)
.then(()=> {
dispatch(saveDataSuccess());
dispatch(NavigationActions.navigate({routeName:'TabContactNavigation'}))
})
.catch((错误)=> {
调度(saveDataFailure(错误))
});
}
}
上面是redux中的Action,它也使用redux-thunk。当成功保存后,单击按钮将数据从表单保存到Firebase时,将调度saveDataSuccess(),然后导航到下一个选项卡。
现在我怀疑问题似乎在这里const userId = firebase.auth()。currentUser.uid,但我不确定。 这是问题的屏幕快照。 (该应用程序运行正常,但出现此警告,我不知道是否应该忽略它),或者我在这里做错了事,需要您的帮助,thanx

https://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
-
您收到此消息是因为您已订阅此线程。
直接回复此电子邮件,在GitHub https://github.com/facebook/react-native/issues/12981#issuecomment-338874018上查看,或使线程https://github.com/notifications/unsubscribe-auth/静音

通常,我将userinfo保存到redux存储中。
因此,我只是根据需要重新使用。
...但是...在类似的情况下,我在超时方面遇到了相同的问题

react-native-signalr库同样存在问题(300000ms)

socket.io服务器选项
pingTimeout(60000)+ pingInterval(25000)<= 60000

关于我们应如何在Android上处理此问题的任何更新? 仍然得到它,也不使用setTimeout ...

只是为了跟进我先前的评论(从8月起),我总结了这里的所有人员的感受:对此AlarmManager感到满意的是,我们只是想知道处理长寿交易的最佳

cc @shergin @cpojer @javache @hramos

Android上对react-native-signalr(ms-signalr-client)的修复是覆盖默认pinginterval(300000):
connection.start({ pingInterval: 5000, jsonp: true, transport: ['webSockets', 'serverSentEvents', 'longPolling']}).done(() => { console.log('Now connected, connection ID =' + connection.id) })

react-native-柚(80000ms)的相同问题

console.ignoredYellowBox = ['Setting a timer'];

这是一种非常安全的解决方法,因为在远程调试时您仍会在chrome的控制台中收到警告

放置控制台忽略代码的最佳位置到底在哪里?

-请不要介意,得到了来自链接的提示stackexchange ,添加到我的App.js如下:

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..

从'react-native'导入{AppRegistry};
从“ ./App”导入应用;

console.ignoredYellowBox = [
“设置计时器”
];

AppRegistry.registerComponent('manager',()=> App);
``

都在工作

@CopyJosh您可以将其放入您的输入文件: index.js

所以还没有任何实际的解决方案? 到现在已经8个月了。

然后让我们解决这个问题。 我们可能必须弄清楚:

A.)可以通过React代码调用的易于扩展的API。 我认为解决仅使AlarmManagers方法之一起作用的做法是明智的。 例如,在您的React Native代码中调用以下方法将通过android设备的Native AlarmManager设置警报。
AlarmMgr.setInexactRepeating(arg1, arg2...)

B.)使此功能生效的实际实现。 据我所知,使用AlarmManager设置警报会将所谓的“待处理的意图”发送到AlarmManager服务。 您告诉AlarmManager您将来希望执行某种类型的“任务”。 在我看来,您需要使AlarmManager(或自定义的React Java方法)将某种类型的数据发送回JavaScript代码,告知其在警报响起后执行什么代码。

有人愿意解决这个问题吗? 在此处可以在AlarmManager上阅读更多内容。

顺便说一句-这种效率低下(与长时间的长时间超时相关)是否仅针对RN版本> 0.43才是新问题? 还是仅从RN> 0.43发出警告? 我从0.43.x迁移到0.47.x,开始看到警告。 我以为效率低下一直存在,而RN现在才开始警告我。

但是,自从几天前迁移以来,我还注意到我的应用在手机上消耗了更多的电池! (并且差异中的其他功能不是明显的罪魁祸首)

@astreet ,您也许还记得发布此问题并在此处添加此警告时指的是什么https://github.com/facebook/react-native/commit/3637bce479吗?

在我开始使用一个设置2分钟重复计时器的lib之后,最近让我感到很烦。因此,我开始深入研究它,以了解为什么首先添加此警告。

现在我担心这句话:“使Timing模块保持唤醒状态”。 我想您可能要指的是Timer模块正在设置Choreographer回调。 尽管无论是否有计时器,似乎都已设置了回调。 在此处查看相关代码部分: https :
没有计划的计时器时,没有代码可以停止回调,添加了计时器时,也没有代码可以开始计划回调。 仅当应用程序移至后台时,该回调才被挂起;移至前景时,该回调将恢复。

结果,无论我们是否有一个长周期,短周期或根本没有定时器的计时器,每个帧的编排者回调都会排队。 在这种情况下,我看不出设置长计时器会如何影响性能。 那么这是否意味着警告是不必要的?

至于将长计时器设置为“正确性问题”,我认为您是指计时器只会在前台应用程序状态下被调用(因此,当您在将来设置较长时间后,应用程序会进入bg它可能不会执行,或者会在应用程序进入前台(可能比您预期的晚得多)时执行。 尽管我认为iOS同样如此,但我们没有显示警告

在socket.io中,默认ping循环为85000ms,= pingInterval(25000ms)+ pingTimeout(60000ms)。 并且应该在服务器中重置这些选项,并确保pingIntervalpingTimeout <= 60000ms之和。

例如:

var socket = require('socket.io')(12345, {
  pingInterval: 20000, 
  pingTimeout: 40000
})

很好奇-我需要能够在我的应用中设置大约5分钟的超时时间。 这个问题有多严重,对我有多大影响?

@ntomallen如果该应用始终在屏幕上显示,则没有任何变化。 会顺利进行。 否则,它可能不会在5分钟后触发。 否则会做得不准确。

我在Android上将laravel echo与React Native一起使用,将套接字服务器选项pingTimeout更改为30000。

@sospedra知道。 我必须进行一些测试以确保它还不错!

有理由不总是使用Handler.postDelayed吗?

任何快速解决此问题? 我刚刚开始将RN与Firebase一起使用。

我尝试了几种不同的计时器解决方案,但始终没有让它在后台工作的任何运气。

我使用setInterval每隔10分钟ping通我的服务器-我刚刚注意到此错误消息,因为我做了setInterval(myFunction, 60000) 。 这是我需要担心的事情吗?

我的预期行为是,在打开应用程序时,它可以发送请求,但是在应用程序挂起(按单个主按钮)后,请求应该停止触发。 这是我可以预期的行为,并且在应用程序暂停时会影响电池寿命吗?

这里没有什么可担心的,警告不正确,应该删除。 没有“ Timing Module”(计时模块)可以保持清醒,只有Choreographer回调可以检查每帧计时器(这也使计时器的最小粒度为〜16ms)。

从计时器不会在iOS或Android的后台触发的意义上说,存在正确性问题。 该警告似乎专门针对Android,但似乎并不准确。 当应用重新回到前台时,所有计时器最终都应触发。

有什么计划很快解决这个问题? 每当我们在Android手机上进行测试时,日志就很烦人。

我的问题…

我收到此错误的原因是我的超时时间高达〜59分钟。 该代码在小时的顶部调用一个方法,并在下一个小时的顶部具有setTimeout来创建setInterval

我的解决方案...

  1. 更新setTimeout以在分钟的开头启动setInterval
  2. 更新setInterval调用的函数,使其仅在当前分钟为0运行该函数。

现在,此功能每分钟运行一次,而不是每小时运行一次……但是,由于它在60次中没有执行59次,因此似乎无害。

@beausmith ,这真的是仅设置60个计时器的解决方案吗? 据我了解,它仍然在同一小时内保持timerModule处于活动状态,但未显示警告:)

@newah-是的,有点怪异...您能提出更好的解决方案吗?

@beausmith ,我尝试使用https://github.com/ocetnik/react-native-background-timer ,它使用本机计时器,这听起来像是一种解决方案-我只是用此lib的实现覆盖了setTimout和setInterval。

根据您的需求,后台支持计时器可能是加号或减号:))

似乎工作正常,但并不能解决我的问题:)

如果我使用react-intl FormattedRelative我也有同样的警告。 由于内部组件FormattedRelative用于计时器:

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

这是我的代码中的使用示例:

<FormattedRelative value={date}>
    {(message: string) => <Text>{message}</Text>}
</FormattedRelative>

有人知道如何解决此警告吗?

这仍然是一个问题。 在Android上使用Firebase服务时,这尤其令人讨厌。 请解决。

对于Firebase服务以及您依赖第三方应用程序的情况,这是一个非常糟糕的错误。 因为如果您在应用之间切换以验证某些内容以继续进行操作,firebase无法正常工作。

一个示例是我们使用第三方/要素登录系统,并使用firebase移动令牌。 但是,由于我们清理令牌后,此人才回到应用程序中。 所以我可以更改清理机制,或者你们可以修复此错误。

@vongohren并不是我完全了解您的用例,但是一种解决方法可能是在进入后台时在您的应用程序中存储后台日期,然后在返回前台时将当前日期与存储的后台日期进行比较,并执行一些清除操作如果一定时间过去了...

详细说明我的用例。 假设您要在另一个应用程序中说“是”以接受登录。 Feks切换到Facebook应用,对第三方的登录请求说“是”。 我正在使用的具体示例是uPort, https ://www.uport.me/

我想我只是坚持认为清除工作可能会在发出信息之后立即进行,因为信息已经发出,因此我们不需要它。 但是,为什么Firebase方法无法在本机反应中起作用? 它停止了它的后台工作者。

我的应用需要30分钟超时。 每次用户与屏幕互动时,都会重置(放弃旧的超时,创建新的超时)。

关于如何正确执行此操作的任何替代方法? 用本机代码处理此问题并在完成后将某些内容传递给React更好吗?

哇,所以这仍然是一个问题

@nbennink在这里检查答案。 当前尚无法保证在后台运行任务的方法,因为有多种因素在起作用(省电,用户交互等)。

使用socket.io后,我也收到同样的警告。
警告如下:

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)

我的包裹详细信息如下:

  • “ react”:“ ^ 16.3.0-alpha.1”,
  • “ react-native”:“ 0.54.4”,
  • “ socket.io”:“ ^ 2.1.1”,
  • “ socket.io-client”:“ ^ 2.1.1”,

找出永久解决方案吗?

使用socket.io后,我也收到同样的警告。
警告如下:

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)

我的包裹详细信息如下:

“ react”:“ ^ 16.3.0-alpha.1”,
“ react-native”:“ 0.54.4”,
“ socket.io”:“ ^ 2.1.1”,
“ socket.io-client”:“ ^ 2.1.1”,

找出永久解决方案吗?

同上,没有办法解决吗?

仍在本机0.57上收到此警告,是否应该打开此问题?

差不多一年了,React Native仍然有同样的问题!!!

面对相同的问题,相同的警告出现3-4次。 很烦人。

是否有解决此问题的解决方案?

此解决方案摆脱了警告消息https://stackoverflow.com/a/48778011/7427111

我想这基本上只是隐藏消息而不能解决问题。

@dhavaljardosh是的,您的猜测是正确的。

我使用Java和Objective C创建了本机计时器。它对我有用,并且隐藏了消息。 我不确定它是否真正提高了性能。 如上所述:对于电池等来说仍然是不好的,因为在后台有很长的计时器。

要问的一个问题是您是否真的需要轮询功能。 我以为自己做了,但是由于这个问题,我意识到我只需要在_some_半频繁的时间段内执行。 所以现在我在应用程序后台运行它,完全避免了这个问题。 YMMV。

使用Pusher时出现同样的问题...

我将测试我的应用程序,以查看每60秒设置一个计时器对性能的影响。
但是,我认为其中有些人对此有经验。 请您分享一下这个经验吗? 影响重大吗?

最新版本仍然存在相同问题。
有什么办法吗?

我也面临这个问题。
该应用程序运行良好,只有在我开始使用Firebase时才发出警告。
有什么办法吗?

我想了解此消息背后的含义,因为我们已经在添加到产品中的最新功能之后开始得到它。 问题_only_是否与在后台运行应用程序时计时器保持运行有关? 如果应用程序已后台运行,订阅应用程序状态事件并停止计时器是否是合适的解决方案? 还是_foreground_中的应用程序长时间运行的计时器也有问题?

我想了解此消息背后的含义,因为我们已经在添加到产品中的最新功能之后开始得到它。 问题_only_是否与在后台运行应用程序时计时器保持运行有关? 如果应用程序已后台运行,订阅应用程序状态事件并停止计时器是否是合适的解决方案? 还是_foreground_中的应用程序长时间运行的计时器也有问题?

也想知道这一点。

此外,setInterval会发生什么? 我没有从这个警告中得到警告,但是它有同样的问题吗?

我想了解此消息背后的含义,因为我们已经在添加到产品中的最新功能之后开始得到它。 问题_only_是否与在后台运行应用程序时计时器保持运行有关? 如果应用程序已后台运行,订阅应用程序状态事件并停止计时器是否是合适的解决方案? 还是_foreground_中的应用程序长时间运行的计时器也有问题?

黄色消息说:“ ...并且只能在应用程序处于前台时调用计时器。”
计时器模块保持唤醒状态,但当应用程序在后台运行时计时器无法运行? 因此,问题在于在后台运行应用程序时使计时器模块保持唤醒状态吗? 我想知道多少性能/电池效果...

@BerndWessels https://www.npmjs.com/package/react-native-firebase你看过吗? 说它允许firebase在本机线程上运行。 不确定这是多么真实,但可能值得一看。 我不确定,您甚至可能正在使用它。

您是否认为如果我切换到该库,是否必须更改现有代码? 我的意思是,那不是很好...

在最新的RN0.59上与Pusher发生相同的问题,并且ui可能会停留几秒钟...

我似乎仅在调用Firebase的实时数据库时遇到此问题。

await firebase.database().ref('users/' + id).set(data);

RN 0.57.1

我还没有用0.59确认。

@swushi我在RN 0.59遇到了同样的问题

使用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 111862ms)

如何摆脱这个警告...

有谁知道如何在不隐藏警告的情况下摆脱它?
我使用的是firebase库,而不是react-native-firebase,但是似乎有相同的问题,我不知道当它投入生产时它将如何影响我。

我真的很担心,如果有人可以帮忙请...

我正在使用以下代码来解决此问题(此刻):

参见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
您可以在独立的.js文件中实现该目标,也可以在使计时器异常的脚本中实现该目标

嗨,是的,上面的代码放在名为“ fixtimerbug.js”的文件中。 然后,将其加载到App.js中,如下所示:

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;

似乎工作正常,它到底能做什么?

非常感谢你@cpmech

嗨,代码(从这里开始:https://github.com/firebase/firebase-js-sdk/issues/97#issuecomment-427512040)只是包装setTimeout (全局)函数来防止它被长期使用。

在我们修改后的global.setTimeout函数中,如果持续时间大于阈值MAX_TIMER_DURATION_MS ,我们将id在本地地图( timerFix )中,然后调用runTask ,它将持续时间分成较小的值。 runTask设置一个超时(使用原始的_setTimeout ),该较小的块将连续执行,直到waitingTime太小为止。 当waitingTime足够小时,我们将React Native的runAfterInteractions称为平滑执行,同时,我们从本地地图中删除id条目,因为我们赢得了在这种情况下,不会再次调用_setTimeout 。 请注意, afterTime被馈入_setTimeout以防止长时间调用它。

否则,在我们修改后的global.setTimeout函数中,如果持续时间小于阈值MAX_TIMER_DURATION_MS ,则我们直接调用全局setTimeout(保存在_setTimeout )。

全局clearTimeout也被包装以通过从本地地图中删除id来执行清理过程。

希望能帮助到你!

面临同样的问题。似乎,我们暂时不得不隐藏警告。 这是最简单的方法:
componentDidMount() { console.disableYellowBox = true; ... }

嗨,代码(从这里开始: firebase / firebase-js-sdk#97(comment) )只是包装setTimeout (全局)函数以防止长时间使用。

在我们修改后的global.setTimeout函数中,如果持续时间大于阈值MAX_TIMER_DURATION_MS ,我们将id在本地地图( timerFix )中,然后调用runTask ,它将持续时间分成较小的值。 runTask设置一个超时(使用原始的_setTimeout ),该较小的块将连续执行,直到waitingTime太小为止。 当waitingTime足够小时,我们将React Native的runAfterInteractions称为平滑执行,同时,我们从本地地图中删除id条目,因为我们赢得了在这种情况下,不会再次调用_setTimeout 。 请注意, afterTime被馈入_setTimeout以防止长时间调用它。

否则,在我们修改后的global.setTimeout函数中,如果持续时间小于阈值MAX_TIMER_DURATION_MS ,则我们直接调用全局setTimeout(保存在_setTimeout )。

全局clearTimeout也被包装以通过从本地地图中删除id来执行清理过程。

希望能帮助到你!

非常感谢! 像魅力一样工作。

嗨,代码(从这里开始: firebase / firebase-js-sdk#97(comment) )只是包装setTimeout (全局)函数以防止长时间使用。

在我们修改后的global.setTimeout函数中,如果持续时间大于阈值MAX_TIMER_DURATION_MS ,我们将id在本地地图( timerFix )中,然后调用runTask ,它将持续时间分成较小的值。 runTask设置一个超时(使用原始的_setTimeout ),该较小的块将连续执行,直到waitingTime太小为止。 当waitingTime足够小时,我们将React Native的runAfterInteractions称为平滑执行,同时,我们从本地地图中删除id条目,因为我们赢得了在这种情况下,不会再次调用_setTimeout 。 请注意, afterTime被馈入_setTimeout以防止长时间调用它。

否则,在我们修改后的global.setTimeout函数中,如果持续时间小于阈值MAX_TIMER_DURATION_MS ,则我们直接调用全局setTimeout(保存在_setTimeout )。

全局clearTimeout也被包装以通过从本地地图中删除id来执行清理过程。

希望能帮助到你!

这是真的解决了问题,还是只是消除了警告?

嗨,代码(从这里开始: firebase / firebase-js-sdk#97(comment) )只是包装setTimeout (全局)函数以防止长时间使用。

在我们修改后的global.setTimeout函数中,如果持续时间大于阈值MAX_TIMER_DURATION_MS ,我们将id在本地地图( timerFix )中,然后调用runTask ,它将持续时间分成较小的值。 runTask设置一个超时(使用原始的_setTimeout ),该较小的块将连续执行,直到waitingTime太小为止。 当waitingTime足够小时,我们将React Native的runAfterInteractions称为平滑执行,同时,我们从本地地图中删除id条目,因为我们赢得了在这种情况下,不会再次调用_setTimeout 。 请注意, afterTime被馈入_setTimeout以防止长时间调用它。

否则,在我们修改后的global.setTimeout函数中,如果持续时间小于阈值MAX_TIMER_DURATION_MS ,则我们直接调用全局setTimeout(保存在_setTimeout )。

全局clearTimeout也被包装以通过从本地地图中删除id来执行清理过程。

希望能帮助到你!

非常感谢! 不会影响应用的整体性能,对吗?

嗨,代码(从这里开始: firebase / firebase-js-sdk#97(comment) )只是包装setTimeout (全局)函数以防止长时间使用。
在我们修改后的global.setTimeout函数中,如果持续时间大于阈值MAX_TIMER_DURATION_MS ,我们将id在本地地图( timerFix )中,然后调用runTask ,它将持续时间分成较小的值。 runTask设置一个超时(使用原始的_setTimeout ),该较小的块将连续执行,直到waitingTime太小为止。 当waitingTime足够小时,我们将React Native的runAfterInteractions称为平滑执行,同时,我们从本地地图中删除id条目,因为我们赢得了在这种情况下,不会再次调用_setTimeout 。 请注意, afterTime被馈入_setTimeout以防止长时间调用它。
否则,在我们修改后的global.setTimeout函数中,如果持续时间小于阈值MAX_TIMER_DURATION_MS ,则我们直接调用全局setTimeout(保存在_setTimeout )。
全局clearTimeout也被包装以通过从本地地图中删除id来执行清理过程。
希望能帮助到你!

这是真的解决了问题,还是只是消除了警告?

不,它不能解决问题。 这只是一个很好的解决方法。

嗨,代码(从这里开始: firebase / firebase-js-sdk#97(comment) )只是包装setTimeout (全局)函数以防止长时间使用。
在我们修改后的global.setTimeout函数中,如果持续时间大于阈值MAX_TIMER_DURATION_MS ,我们将id在本地地图( timerFix )中,然后调用runTask ,它将持续时间分成较小的值。 runTask设置一个超时(使用原始的_setTimeout ),该较小的块将连续执行,直到waitingTime太小为止。 当waitingTime足够小时,我们将React Native的runAfterInteractions称为平滑执行,同时,我们从本地地图中删除id条目,因为我们赢得了在这种情况下,不会再次调用_setTimeout 。 请注意, afterTime被馈入_setTimeout以防止长时间调用它。
否则,在我们修改后的global.setTimeout函数中,如果持续时间小于阈值MAX_TIMER_DURATION_MS ,则我们直接调用全局setTimeout(保存在_setTimeout )。
全局clearTimeout也被包装以通过从本地地图中删除id来执行清理过程。
希望能帮助到你!

非常感谢! 不会影响应用的整体性能,对吗?

不,它根本不影响性能。

快速说明

如果麻烦,您只需添加console.ignoredYellowBox = ['设置计时器'];

面临同样的问题。似乎,我们暂时不得不隐藏警告。 这是最简单的方法:
componentDidMount(){console.disableYellowBox = true; ...}

这不是可行的解决方案。 错误仍然会发生,您只是没有收到通知。

结果? 仍然需要进行错误解析。

例如,在使用Firebase侦听器的情况下,您将隐藏大量错误,但是您的开发环境仍将处理它们。

恰当的例子:我的基于expo的项目一直崩溃,因为它试图对每个计时器错误进行源映射。

我关闭这个是因为我认为React Native不会在核心中添加对AlarmManager的支持。 可以使用第三方模块或自定义本机代码来完成。

@cpmech的解决方案有效吗? 我在RN60.4上尝试过,但是收到了很长的计时器警告。

嗨,我想我找到了解决方案:
首先,您必须在项目中找到以下文件:libraries / Core / Timers / JSTimer; js
打开它,您只需要更改此常量MAX_TIMER_DURATION_MS,以增加您的持续时间,在警告结尾处写道!

增加计时器,但是多少?

@dulmandakh是否有任何开源项目可以解决您所知道的此问题?

@dulmandakh是否有任何开源项目可以解决您所知道的此问题?

RNFirebase也许? @dulmandakh

您可以将计时器重新安排为固定的时间,直到到期为止:


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

已经有2年的时间本机或Firebase会正确解决此问题。 :(

在经过数小时的长时间调查之后,我想知道的是我是否以某种方式造成了此问题。
我不确定它何时出现。
我致电Firestore时,它会弹出吗?
我的应用程序没有使用任何计时器

@luismasg我没有在代码中使用setTimeout,因为这是一种不好的做法,但是我知道错误的根源,并且我无法停止它,似乎它与我的数据库建立了远程连接,显然是我正在使用集的库保持TTL超时的时间,检查您的依赖库,看看是否可以识别出导致问题的原因

老实说,无论如何,对于长计时器来说,我不认为使用JS计时器/间隔不是一个好主意,警告是有原因的。

使用生命周期事件来添加/删除短计时器。 如果需要实际的后台执行,请将本机代码与前台服务(Android)和后台任务(iOS)结合使用。

老实说,无论如何,对于长计时器来说,我不认为使用JS计时器/间隔不是一个好主意,警告是有原因的。

如上所述,许多人都在为使用更长计时器的库而苦恼。 “只是不使用firebase”不是解决方案。

显然,这是一个经常遇到的问题,对其进行处理将改善react-native的开发人员体验,这听起来像是它的最终目标...

我不会说“不使用Firebase”是答案,更像是“修复Firebase使其不使用长计时器,并使用适当的本机构建块来执行他们使用长计时器的任务”。

但是您是对的,以某种方式支持RN是理想的,但是考虑到所有警告(例如更高的电池消耗,不必要的后台执行时间等),这只会使开发人员步履蹒跚。 如果有的话,它应该是一个单独的计时器/间隔原语。

如果有的话,它应该是一个单独的计时器/间隔原语。

我对这个问题的理解是缺少这样一个原始的😄

在计时器内使用计时器,就这样!

@dulmandakh为什么这个问题结束了? 问题仍然存在,讨论正在进行中吗?

我将此添加到App.js中,并对其进行了修复(在正式修复之前是临时的)

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

这是一种解决方法,而不是解决方法。

我将此添加到App.js中,并对其进行了修复(在正式修复之前是临时的)

...
    if (typeof id === "string" && id.startWith("_lt_")) {
...

如果要使用该代码,则“ startWith”应为“ startsWith”。

我正在使用AWS Amplify数据存储库来体验这一点。 代替适当的修复程序,我通过禁用警告

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

对我而言,目前尚不清楚根本问题是RN需要修复,Amplify需要修复还是需要修补。 显然,我不希望出现性能问题。

如果麻烦,您只需添加console.ignoredYellowBox = ['Setting a timer'];

我应该在哪里添加我在屏幕文件和操作文件中尝试过的内容,仍然无法正常工作

只需将其放在App.js文件中的某个位置即可。 我把它放在我的构造函数中。
不知道那是最好的地方,所以如果有人知道什么更好的话,我想听听!

我认为使用Firebase的任何人都可以解决此问题(登录/注册后),配置应用程序的持久性

*创建新用户后,他将自动登录

https://firebase.google.com/docs/auth/web/auth-state-persistence

所以...验证用户身份后,将创建一个时间变量。

firebase的默认值为local 。 “ firebase.auth.Auth.Persistence.LOCAL”

您可以使用以下方法进行更改:
firebase.auth.Auth.Persistence.SESSION
firebase.auth.Auth.Persistence.NONE

或使用localStorage ...

直到他们确定性地解决了...

从“ react-native”导入{YellowBox};
从“ lodash”导入_;
YellowBox.ignoreWarnings([“设置计时器”]);
const _console = _.clone(控制台);
console.warn =(消息)=> {
如果(message.indexOf(“设置计时器”)<= -1){
_console.warn(message);
}
};

解决后,垃圾代码将被删除,瞧!

这可以用RxJS解决。

基本上将您的5200计时器拆分为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 !'

我认为使用Firebase的任何人都可以解决此问题(登录/注册后),配置应用程序的持久性

*创建新用户后,他将自动登录

https://firebase.google.com/docs/auth/web/auth-state-persistence

所以...验证用户身份后,将创建一个时间变量。

firebase的默认值为local 。 “ firebase.auth.Auth.Persistence.LOCAL”

您可以使用以下方法进行更改:
firebase.auth.Auth.Persistence.SESSION
firebase.auth.Auth.Persistence.NONE

或使用localStorage ...

大! 但是对于Firestore呢?

我认为使用Firebase的任何人都可以解决此问题(登录/注册后),配置应用程序的持久性
*创建新用户后,他将自动登录
https://firebase.google.com/docs/auth/web/auth-state-persistence
所以...验证用户身份后,将创建一个时间变量。
firebase的默认值为local 。 “ firebase.auth.Auth.Persistence.LOCAL”
您可以使用以下方法进行更改:
firebase.auth.Auth.Persistence.SESSION
firebase.auth.Auth.Persistence.NONE
或使用localStorage ...

大! 但是对于Firestore呢?

如果您使用的是旧的Firebase SDK,请迁移到firestore admin SDK。

大多数问题将得到解决

https://firebase.google.com/docs/reference/admin

仍然没有人能够解决这个问题。 #让开发人员感到羞耻; p

仍然没有人能够解决这个问题。 #让开发人员感到羞耻; p

永远不要羞于开源贡献者。 遗憾的是,此问题尚未得到解决,但是源代码是开放的,如果您知道如何解决,我相信他们会喜欢请求请求的。

那就是为什么这个问题在地球上是封闭的

因为它应该在有问题的库中修复。 而且令人讨厌的库看不到其实现方式有问题。

因此,没有人会修复它,因为双方都不认为它已损坏。

他们可以为此感到羞耻_

伙计们,我认为这还没有“解决”,原因很简单,那就是使用长计时器是一个极其糟糕的主意。

如果您想将来在后台/事件中运行计时器,则需要一个本机库来执行。 由于后台执行限制,这在两个平台上也特别困难。

基于@eightyfive的注释,我们替换了rxjs6 delaytimeoutinterval函数。

仍然存在一个问题,有人可以解释使用较小的时间间隔时“计时器模块”是否保持锁定吗? 基本上,只是在应用程序不在前台时导致计时器暂停。 还是这只是隐藏了问题?

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

有趣的是,该线程中的每个人都在讨论解决方法,以忽略此警告。
当我从警告重定向到此“问题”时,我希望找到适当的文档,解释“如何”? 处理它,还有更多关于“为什么?”的理由。

前端#千禧一代

这个#millenial想要指出:

  • 此错误不需要文档,这是不言自明的:您设置了长时间计时器。
  • 这个线程到处都是人们忽略不拥有的库的警告(例如,firebase)
  • 正如该线程中的(富有成效的)讨论所表明的,这是一个更复杂的问题,需要在react-native

就是说,我再次指出不应关闭此问题,将其标记为known-issueHelp Wanted

千禧年对千禧年的回答:)

此错误不需要文档,这是不言自明的:您设置了长时间计时器。

  • 它不是错误,是警告(不要问我差异,否则我们必须开始深刻的哲学对话:))
  • 由于提供了对此票证的引用,因此它已经被记录在文档中,在这里我需要阅读大量评论而不是执行摘要(有点像您已经建议的已知问题):
    image
  • 我不会说这是“自我解释”。 提供的上下文不足。 从字面上看,描述中有两个句子。

就是说,我将再次指出该问题不应关闭,它被标记为已知问题和帮助通缉。

完全同意。 这将节省许多来自警告中URL引用的人员的时间。

对于Firebase / firestore用户:我只是简单地直接使用REST端点进行Firestore调用。 由于我只需要auth和firestore,因此很容易解决了我的问题。 此处的代码段:

https://stackoverflow.com/a/62446792

我在App()中做到了,如下所示:

从'react-native'导入{YellowBox};
导出默认函数App(){
YellowBox.ignoreWarnings(['设置计时器']);
...
...
..
}

记住

我做了什么,并且正在和我一起工作,但是无论是否是一种好的做法,我仍然不了解

导航到文件

node_modulesreact-native \ Libraries \ Core \ TimersJSTimers.js

有一个功能const MAX_TIMER_DURATION_MS = 60 * 1000 ,我将时间增加为60 * 100000,它出现了

嘿,
这个问题大约3年了,我们仍然有这个警告;)
正如@RWOverdijk所说,忽略警告不是解决方案。
我已经错过了解决方案吗?

谢谢<3

大家好,我们决定锁定此问题。 我知道这个问题令许多人感到沮丧,我想抽出一些时间来了解我们为什么要做出这个决定。

计时器在React Native中如何在Android上工作

React Native具有JS计时器的自定义实现,例如setTimeout 。 在Android上,其工作方式是在本机端跟踪JS计时器,然后由本机端确定何时触发这些计时器。 这使React Native可以更聪明地了解计时器的触发时间,尤其是它们与应用程序生命周期和渲染的关系。

如果我将定时器设置为长间隔会怎样?

通过阅读代码并进行一些测试,这是我的理解:

  1. 如果您设置了一个较长的计时器,并且在计时器处于活动状态的过程中该应用保持打开状态,则该计时器仍应正常工作。
  2. 如果您设置了很长的计时器,并且在计时器结束之前手机已进入后台,则直到您下次打开应用程序时,计时器才会被激活。
  3. 无头JS任务有一个例外,即使应用程序在后台,它也可以使计时器保持工作状态。

为什么我们不应该长时间间隔调用计时器?

我认为这主要是一个正确性问题,而与性能无关。 问题是,如果用户后台运行您的应用程序,则您不能依赖长时间的计时器。

如果您不介意稍后再次显示应用程序时激活计时器,那么我认为忽略YellowBox警告是个好主意。

另一方面,如果希望在会话的整个生命周期中都调用计时器,并且不应在前台再次触发它,则需要执行一些操作以确保在前台忽略该计时器。

如何使用设置长计时器的第三方库(例如Socket.io和Firebase)?

我不知道这些第三方库的详细信息。 最终归结为上述问题。 如果这些第三方库在处理在前台解决的计时器时遇到问题,那么您将需要找出一种解决方法。 例如,上面的一些评论提出了针对Firebase进行此操作的方法。 最终,尽管如此,您可以依靠依赖于React Native专门开发的库来获得更好的服务。

另一方面,如果第三方库在前台解决计时器时没有问题,则可以忽略该错误。

为什么setTimeout不能像最初建议的那样经过AlarmManager

AlarmManager如果在后台会唤醒应用程序,我们不认为像setTimeout这样的计时器会唤醒应用程序。 这些长计时器中的大多数是为超时等设置的​​,这些仅在打开应用程序时才相关。 在后台唤醒应用程序的成本很高,只有在开发人员明确具有此意图的情况下才可以这样做。

同时,许多人可能需要这样的东西。 我们可以为它开发一个不会通过setTimeout的API。 但是由于目前精益核心的努力,我们实际上正在尝试避免增加React Native的API面。 我们认为这是最好由第三方库react-native-background-timer处理的任务。

那您为什么不完全删除警告呢?

我们希望开发人员知道发生了什么。 如果有人安装了依赖setTimeout正确性的库,我们认为开发人员应该意识到我们不能保证这种正确性。 我们希望让每个开发人员自行决定该警告在他们的特定用例中是否重要。

此页面是否有帮助?
0 / 5 - 0 等级