【问题标题】:JS: check if setTimeout has finished or been canceledJS:检查 setTimeout 是否已完成或被取消
【发布时间】:2019-02-05 22:54:47
【问题描述】:

我正在创建一个脚本,该脚本将在经过一定时间后执行任务。我希望用户能够取消这些任务的执行。我可以通过将超时保存到一个列表中来做到这一点,然后我用它来取消所有超时。但是,如果超时正常完成,它仍会存储在该列表中。

在尝试清除超时之前,如何检查超时是否已经完成或取消?

var timeouts = [];

$(document).on('click', '.doTask', function() {
    var timeout = setTimeout(() => {
        doTaskAfter();
    }, 10000);
    timeouts.push(timeout);
});

$(document).on('click', '.cancelTasks', function() {
    var i = timeouts.length;
    while (i--) {
        if (timeouts[i].finished || timeouts[i].timeoutCleared) { // How to I check this?
            clearTimeout(timeouts[i]);
        }
        timeouts.splice(i, 1);
    }
});

【问题讨论】:

  • 据我所知,您需要自己跟踪超时的完成情况
  • 您可以在完成后从timeouts 数组中删除计时器ID。然后当您稍后遍历timeouts 时,您就会知道您不会遇到已完成的计时器。
  • 我可能不完全理解这个问题,但你为什么关心超时是否完成?您似乎想取消所有计时器,为什么不在您的while 中添加clearTimeout(timeouts[i])

标签: javascript


【解决方案1】:

我认为你可以使用 Promise 来做到这一点。

每次你创建一个计时器,把它放在一个promise中,然后把这个promise推到数组中。一旦计时器运行,承诺将解决。

按字面意思写你的计时器,比如..

   setTimeout(() => {
       resolve("True");
    }, 10000);

从那里,你能做的就是这个。遍历代码时,使用 promise.race 以及返回 false 的第二个 promise。

let race = [timeouts[i],Promise.resolve("False") ]

使用 Promise.race 来查找 Promise 是否已解决。这是可行的,因为如果它们都已解决,Promise.race 将返回第一个 Promise,它将返回“True”。如果您的计时器仍然超时,那么它将返回 false。

Promise.race(race).then((res, rej) => {
if(res === true) {
clearTimeout(timeouts[i]);
}
})

【讨论】:

    【解决方案2】:

    我不知道我是否理解正确,但是为什么要删除已经完成的超时?

    一旦完成,超时就可以从数组中删除:

    timeouts.splice(timeouts.indexOf(timeout), 1);
    

    否则,您可以使用 clearTimeoutsplice 从超时列表中终止所有已注册/正在运行的超时。

    var timeouts = [];
    
    $(document).on('click', '.doTask', function() {
        var timeout = setTimeout(() => {
            doTaskAfter();
            timeouts.splice(timeouts.indexOf(timeout), 1); // <=== HERE
        }, 10000);
        timeouts.push(timeout);
    });
    
    $(document).on('click', '.cancelTasks', function() {
        var i = timeouts.length;
        while (i--) {
            clearTimeout(timeouts[i]);
            timeouts.splice(i, 1);
        }
    });
    

    【讨论】:

      【解决方案3】:

      可能会或可能不重要的一件事是在已清除或完成的超时 doesn't do anything 上调用 clearTimeout,因此您可能不需要跟踪它。

      否则,您可以只跟踪状态,例如:

      var timeouts = [];
      
      $(document).on('click', '.doTask', function() {
          var timeout = { state: 'waiting' };
          timeout.id = setTimeout(() => {
              timeout.state = 'finished';
              doTaskAfter();
          }, 10000);
          timeouts.push(timeout);
      });
      
      $(document).on('click', '.cancelTasks', function() {
          var i = timeouts.length;
          while (i--) {
              if (timeouts[i].state !== 'finished' && timeouts[i].state !== 'canceled') {
                  // i.e. timeouts[i].state is 'waiting'
                  clearTimeout(timeouts[i].id);
                  timeouts[i].state = 'canceled';
              }
              timeouts.splice(i, 1);
          }
      });
      

      【讨论】:

        【解决方案4】:

        只需将包含您需要执行的代码的函数放入设置的超时时间,如下所示?:

        setTimeout(() => { youfunction()}, 2000)
        
        yourfunction(){
        
        put your code here
        }
        

        yourfunction 将在 2 秒后执行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-14
          • 2020-02-24
          • 2016-08-29
          • 1970-01-01
          相关资源
          最近更新 更多