【问题标题】:Javascript setInterval with web worker slows down in mobile browser带有网络工作者的Javascript setInterval在移动浏览器中变慢
【发布时间】:2021-08-05 09:28:06
【问题描述】:

我正在使用 Javascript setInterval 和 web worker 实现倒数计时器。它在桌面上运行良好,但在移动浏览器中,当浏览器最小化(非活动模式)时,计时器会变慢。

有没有办法防止移动设备中的 setInerval 减速问题?

这是我的代码的一瞥:

script.js

var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
  hidden = "hidden";
  visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
  hidden = "msHidden";
  visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
  hidden = "webkitHidden";
  visibilityChange = "webkitvisibilitychange";
}

document.addEventListener(visibilityChange, function (event) {
  if( document[hidden] === false ){
      // distance is a value of difference between current time and the end time

      var days = Math.floor(distance / (60 * 60 * 24));
      var hours = Math.floor((distance % (60 * 60 * 24)) / (60 * 60));
      var minutes = Math.floor((distance % (60 * 60)) / 60);
      var seconds = Math.floor(distance % 60);

      var secondsLeft = (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;

      startTimer(distance, secondsLeft);
  }
});


function startTimer(distance, secondsLeft)
{
   // First check whether Web Workers are supported
   if (typeof(Worker)!=="undefined"){
      // Check whether Web Worker has been created. If not, create a new Web Worker based on the Javascript file simple-timer.js
      if(w == null){
        
        w = new Worker("../js/timer-worker.js");

        w.postMessage({ 
            'distance': distance,
            'secondsLeft': secondsLeft
        });
      }
      // Update timer div with output from Web Worker
      w.onmessage = function (event) {
        console.log(event.data.time_left_str);
      };
   } else {
      // Web workers are not supported by your browser
      console.log('Sorry, your browser does not support Web Workers ...');
   }
}

timer-worker.js

var timerStart = true;

function myTimer(distance)
{
   function pad(n) {
      return (n < 10 ? "0" + n : n);
   }

   var hours = Math.floor((distance % (60 * 60 * 24)) / (60 * 60));
   var minutes = Math.floor((distance % (60 * 60)) / 60);
   var seconds = Math.floor(distance % (60));

   var total_seconds = (hours * 60 * 60) + (minutes * 60) + seconds;

   if( hours > 0 ){
      time_left_str = pad(hours) + " hrs " + pad(minutes) + " mins " + pad(seconds) + " secs ";
   }
   else if( minutes > 0 ){
      time_left_str = pad(minutes) + " mins " + pad(seconds) + " secs ";
   }
   else{
      time_left_str = pad(seconds) + " secs ";
   }

   // return output to Web Worker
   postMessage({
      'time_left_str': time_left_str,
      'total_seconds': total_seconds,
      'distance_changed': distance
   });
}


if (timerStart){
   distance = null;
   secondsLeft = null;

   self.addEventListener('message', function(event) {
      if(typeof(event.data.distance)!=="undefined"){
         distance = event.data.distance;
      }
      if(typeof(event.data.secondsLeft)!=="undefined"){
         secondsLeft = event.data.secondsLeft;
      }
      
   }, false);

   // get current time
   var d0=(new Date()).valueOf();
   // repeat myTimer(d0) every 100 ms
   myVar = setInterval(function(e){
      //console.log('distance :: ' + distance);
      myTimer(distance, secondsLeft);

      distance--;
   }, 1000);
   // timer should not start anymore since it has been started
   timerStart = false;
}

【问题讨论】:

  • setIntervalsetTimeout保证准时到达,请参阅 this section on MDN 了解更多详情。没有办法避免这种情况,因为这不是缺陷,而是用户方面的好处:随机网站不能随意占用浏览器。
  • 我的要求是确保计时器运行,而不管浏览器在移动设备中是否处于非活动状态。正如我所说,它在我在桌面测试的所有浏览器中都能完美运行。只有移动浏览器存在问题。到底有没有出来?

标签: javascript setinterval web-worker countdowntimer


【解决方案1】:

为什么即使没有显示浏览器,您的倒计时也需要每秒运行一次?我认为这不是您的需要,而是在用户观看时显示准确的倒计时。

与其在每个计时器上递减计数器,希望它每秒钟精确执行一次,不如只重新计算从页面首次加载的那一刻起的距离,以防止发生任何危险效应:

//happens on the loading of the page
var d0 = new Date();
var initDistance = //compute initial distance here
var distance = initDistance;

// ... in the refresh function
    var distance = //recompute distance based on initDistance and the difference between new Date() and d0

// do the same for secondLeft if needed.

【讨论】:

  • 我需要通过 ajax 获取的服务器时间。 var d0 = new Date(); 在我的情况下不起作用。
  • 那为什么不直接获取一次,存储对应的客户端时间,并作为参考呢?
  • 不,我一次无法获取。它是一个拍卖门户,拍卖的结束时间会根据其他一些条件不断变化。所以我必须通过ajax获取拍卖结束时间,并计算服务器时间和拍卖结束时间之间的差异。
  • 好的,首先我认为您需要将这些信息放在您的问题上,因为这非常重要。其次,您是否有理由发送垃圾邮件请求而不使用 websockets 之类的东西?如果你只能拉我的建议是做一个混合:每秒和每 x 秒倒计时,请求服务器重新同步。
猜你喜欢
  • 2011-11-10
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
  • 2021-12-25
  • 2011-04-27
  • 2019-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多