为啥setTimeout倒计时不能按时处理

分类:前端来源:站内 最近更新:2020-09-10 20:31:54浏览:1415留言:0

为啥setTimeout倒计时不能按时处理

我们经常会遇到这样的情况,设置了setTimeout倒计时时间3秒,然后执行程序后发现远远超过了3秒后才执行。我们先尝试用简单的实例,一步步的搞懂js执行机制。

console.log(1);
setTimeout(() => {
  console.log(2);
}, 3000);
console.log(3);

结果分别打印出:1,3,2


我们把倒计时时间改为0,看看结果

console.log(1);
setTimeout(() => {
  console.log(2);
}, 0);
console.log(3);

结果依旧打印出:1,3,2


我们在倒计时函数后面加上复杂的逻辑处理(实例用阻塞函数)

function sleep(ms) {
  let start = new Date().getTime();
  while (new Date().getTime() < start + ms);
}

console.log(1);
setTimeout(() => {
  console.log(2);
}, 3000);
sleep(5000);
console.log(3);

结果依旧打印出:1,3,2

直至这里,我们就复现了为啥设置的倒计时时间不管用的问题,倒计时之后如果有其他耗时的处理,之前的倒计时时间就不能按照预想的执行了。


结论有了,我们再来了解JS执行机制

js是单线程的,Js类型中一切的多线程的说法都是单线程模拟出来的。既然是单线程,那js执行语句都是按照顺序执行。但是现实中不允许我们这样做,就好比去银行排队办业务,我们不能因为一个人没有带身份证,而让后面的人等他回去取了身份证办理完业务才下一个。所以就出现了同步任务和异步任务,你回去拿你的身份证,下个人继续办理业务。

如图:

1599716954749828103.jpg

  1. Js在执行代码时,同步的进入主线程,如只有一个窗口的银行排队。如果遇到异步如setTimeout等命令时(忘记带身份证回去取),进入Event Table里。

  2. Event table里面完成之后,进入Event Queue。这个时候不能给你插队进入主程序执行,要到所有主程序完成之后,才能处理Event Queue里的程序。

  3. 如果主程序中有个程序同步执行比较浪费时间(如果sleep),Event Queue也不能插队处理,你也得等着,即便你设置为0,回家拿个身份证很快也没用。

让我们在衍生一下

ajax或者Promise也要等主程序执行完成吗?

答案不是

他们两个就好比银行的VIP客户,你只要拿到身份证了,随时可以插队处理。

看看下面的代码打印出什么结果

console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})


答案:1,7,6,8,2,4,3,5,9,11,10,12。

1

发表评论

评论列表(0)

  • 暂时没有留言
热门