最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Timers(setInterval) in ionic apps go to sleep after some time in the background - Stack Overflow

programmeradmin3浏览0评论

My ionic app has a timer(a simple setInterval that ticks every second) which works perfectly fine when the app is in the foreground. However when the app goes to the background and es back to the foreground after 10 minutes, the time displayed in the app is wrong (the time is much less that it should be). I have tried adding the timer into a directive and also using the native DOM manipulation api(document.getElementById, etc) methods, but they both didn't work. I think the ionic framework is doing something to the view and bindings when the app goes to the background. Has anyone experience such a issue and if so how did you guys manage to fix it?

My ionic app has a timer(a simple setInterval that ticks every second) which works perfectly fine when the app is in the foreground. However when the app goes to the background and es back to the foreground after 10 minutes, the time displayed in the app is wrong (the time is much less that it should be). I have tried adding the timer into a directive and also using the native DOM manipulation api(document.getElementById, etc) methods, but they both didn't work. I think the ionic framework is doing something to the view and bindings when the app goes to the background. Has anyone experience such a issue and if so how did you guys manage to fix it?

Share Improve this question edited Aug 21, 2015 at 22:29 Lakmal Caldera asked Aug 19, 2015 at 7:08 Lakmal CalderaLakmal Caldera 1,0312 gold badges14 silver badges25 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 9

After hours of searching for an answer, I finally came up with my own hack. I hope this solution might help others who e across a similar issue.

When the app goes to the background, at some random time, the timer stops ticking and goes to sleep till the app is brought back the foreground. When the app es up to the foreground, the timer starts ticking again from the point where it went to sleep.

  • Solution/Hack:

    1. Record the timestamp in a separate variable(in seconds) and have it updated in each interval of the timer.

      var timeStamp = Math.floor(Date.now() / 1000);

    2. Check each interval of the timer if the difference between your previous interval's timeStamp and the latest(new) timeStamp is greater than one second. If the condition is met, add the difference between those two timestamps to your ticking time.

  • How it works:

    App in Foreground

    1. Just Before timer start ticking
      - Time stamp recorded (Assume 1 second)
    2. Timers start ticking
      - check condition if(currentTimeStamp - previousTimeStamp > 1) { Add the the above difference to the time } Before the interval ends, update the TimeStamp variable with the currentTimeStamp.
      In the first interval, the currentTimeStamp should be either 1 second or 2 second depending on weather you are offloading the timer into a setTimeout. Thus the difference will definitely be 0 or 1. Since the condition doesn't match we update the timestamp with 1 or 2 seconds and move on to the next interval. As long as the timer doesn't go to sleep our condition will fail.

    App in Background

    Strangely after 10 minutes, the timer goes to sleep(our timer is literally losing track of time from now because the next interval is not firing).

    App return from Background to foreground

    The timer starts ticking from where it stopped(i.e. the next interval). Now the difference in our condition should be more than one second and thus adding that difference(basically the lost time) to our current ticking time.

  • Code:

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

    Note: This solution work standalone(vanilla Js with native DOM api) and also works great in angular directives.
    You can increase the deltaTime of the above code to 2 to be a little more accurate if by any chance your single thread is busy somewhere else with some other task.
    P.s I'm actually running the ionic app inside my own instance of a webview and not cordova so I can't use any fancy cordova plugin.

    Ionic/Cordova apps goes to sleep when in background mode. But you could look at this: https://github./katzer/cordova-plugin-background-mode

    Here is a little bit updated code from the original answer

    var interval = null;
    var timerSecondsTotal = 0;
    
    function runTimer() {
          var prevTickTimestamp = Date.now()
    
          interval = setInterval(() => {
            var currentTickTimestamp = Date.now()
            var delta = currentTickTimestamp - prevTickTimestamp
    
            timerSecondsTotal += Math.round(delta / 1000)
    
            prevTickTimestamp = currentTickTimestamp
          }, 1000)
        }
    
  • 发布评论

    评论列表(0)

    1. 暂无评论