【问题标题】:Creating custom setTimeout() function创建自定义 setTimeout() 函数
【发布时间】:2021-06-16 08:20:26
【问题描述】:
var td = {
setTimeout: function(callback, ms){
var dt = new Date();
    var i = dt.getTime(), future = i+ms;
    while(i<=future){
      if(i === future){
        callback();
      }
      // i = dt.getTime();
      i++;
  }
 }
};
td.setTimeout(function(){
    console.log("Hello"); // executes immediately
}, 3000);

这种方法的问题在于,在 while 块的末尾,我将 i 的值设置为 i + 1,我认为应该将其设置为当前时间戳 (dt.getTime()),这样,future(回调函数应该执行的时间戳值)可以与当前时间戳进行比较,即i的值。

但是当我注释掉i++ 并取消注释这一行时:

i = dt.getTime();

并运行脚本,浏览器冻结。有没有办法创建一个与window.setTimeout() 具有相同目的的setTimout() 方法?

【问题讨论】:

  • 实际上不可能在用户空间代码中模拟setTimeout,因为JavaScript 没有公开任何API 来直接将函数添加到事件队列。无论如何......你的问题是什么?
  • 您应该明白,即使您修复了无限循环问题,浏览器仍然会锁定。那是因为循环会阻止其他任何东西被执行,直到它终止。
  • 看看this answer 或多或少类似的问题。

标签: javascript


【解决方案1】:

您的代码的问题是,dt.getTime() 总是返回相同的值(即创建 dt 对象的时间。要使其正常工作,您需要这样做

dt = new Date();

在你设置之前

i = dt.getTime();

【讨论】:

  • 这正是他正在做的事情。
  • @ibrahimmahrir:不,不在循环中。
  • 我宁愿使用Date.now()的原因之一...没有理由保留最新的对象。
  • @ibrahimmahrir:你基本上是对的。但是dt.getTime() 持有循环永远!想象一下它返回5。然后i++ 变成6。在下一次迭代中,i = dt.getTime() 将其重置为 5...i 永远不会真正增加。获取当前时间至少可以修复无限循环。但正如您从我的 cmets 中看到的那样,我已经指出这不是正确的方法。
  • @ibrahimmahrir 我想每个人在冒险进入 JavaScript 的神秘领域时至少会遇到一次这样的事情;)
【解决方案2】:

看.. setTimeout 不同步 >:D

function timeout(fn,n){
  (async()=>{
    n=n||0; var time=Date.now()+n
    await new Promise(r=>r()) //asynchronous even if n is 0
    while(Date.now()<time){
      await new Promise(r=>r())
    }
    fn()
  })()
  return true
}

//demonstration
timeout(()=>console.log(3),200)
timeout(()=>console.log(2),20)
console.log(1)

【讨论】:

  • 它...不过并没有真正做超时。 codepen.io/davelnewton/pen/poeqYyK
  • 我放错了几行;-;
  • 修复“工作”的延迟,但与任何繁忙的循环一样,这将锁定 CPU。
猜你喜欢
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多