/ 前端
分类:前端来源:站内 最近更新:2020-09-10 20:31:54浏览:1660留言:0
我们经常会遇到这样的情况,设置了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执行语句都是按照顺序执行。但是现实中不允许我们这样做,就好比去银行排队办业务,我们不能因为一个人没有带身份证,而让后面的人等他回去取了身份证办理完业务才下一个。所以就出现了同步任务和异步任务,你回去拿你的身份证,下个人继续办理业务。
如图:
Js在执行代码时,同步的进入主线程,如只有一个窗口的银行排队。如果遇到异步如setTimeout等命令时(忘记带身份证回去取),进入Event Table里。
Event table里面完成之后,进入Event Queue。这个时候不能给你插队进入主程序执行,要到所有主程序完成之后,才能处理Event Queue里的程序。
如果主程序中有个程序同步执行比较浪费时间(如果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。