我的离子应用程序有一个计时器(一个简单的setInterval,每秒滴答),当应用程序在前台时,它可以正常工作.然而,当应用程序进入后台并在10分钟后返回到前台时,应用程序中显示的时间是错误的(时间远小于应该的时间).我已经尝试将计时器添加到指令中,并且还使用本机DOM操作api(document.getElementById等)方法,但它们都不起作用.我认为当应用程序进入后台时,离子框架正在对视图和绑定做一些事情.有没有人遇到这样的问题,如果是这样,你们是如何设法解决它的?
经过几个小时的寻找答案,我终于找到了自己的黑客.我希望这个解决方案可以帮助遇到类似问题的其他人.
当应用程序进入后台时,在某个随机时间,计时器停止滴答并进入睡眠状态,直到应用程序返回前台.当应用程序到达前台时,计时器会从它进入睡眠状态的位置再次开始计时.
解决方案/哈克:将时间戳记录在单独的变量中(以秒为单位),并在计时器的每个间隔中更新时间戳.
var timeStamp = Math.floor(Date.now()/ 1000);
如果先前间隔的timeStamp与最新(新)timeStamp之间的差异大于一秒,请检查定时器的每个间隔.如果满足条件,请将这两个时间戳之间的差异添加到您的滴答时间.
应用程序在前景中
在计时器开始计时之前
- 记录时间戳(假设1秒)
定时器开始滴答
- 检查条件
if(currentTimeStamp - previousTimeStamp > 1)
{
Add the the above difference to the time
}
Before the interval ends, update the TimeStamp variable with the currentTimeStamp.
在第一个间隔中,currentTimeStamp应该是1秒或2秒,具体取决于您将计时器卸载到setTimeout的天气.因此差异肯定是0或1.由于条件不匹配,我们用1或2秒更新时间戳并继续下一个间隔.只要计时器没有进入睡眠状态,我们的状态就会失败.
应用程序在后台
10分钟后奇怪的是,计时器进入睡眠状态(我们的计时器从现在开始失去时间跟踪,因为下一个时间间隔没有开始).
应用程序从背景返回到前景
计时器从停止的位置(即下一个间隔)开始计时.现在,我们的条件差异应该超过一秒,从而将这个差异(基本上是丢失的时间)加到我们当前的滴答时间.
码:var transactionTime = 0; //Initial time of timer var timeStamp = Math.floor(Date.now() / 1000); var deltaDelay = 1; setInterval(function () { if (transactionTime != 0 && (Math.floor(Date.now() / 1000) - timeStamp) > deltaDelay) { transactionTime += (Math.floor(Date.now() / 1000) - timeStamp); } timeStamp = Math.floor(Date.now() / 1000); //Update your element with the new time. window.document.getElementById("transaction_timer").innerHTML = util.formatIntoHHMMSS(transactionTime++); }, 1000);
注意:此解决方案独立工作(带有原生DOM api的vanilla Js),并且在angular指令中也很有用.
您可以将上面代码的deltaTime增加到2,以便在您的单个线程忙于某个其他任务的其他任何地方时更准确一些.
Ps我实际上在我自己的webview实例中运行离子应用程序而不是cordova所以我不能使用任何花哨的cordova插件.