js return false 之后不能停止执行_浏览器是如何执行JavaScript异步代码的?

c6336a11206ede55a3bc590a8ae3c8f4.png

例子:下题你可能会认为100ms之后,由于a变成了false,所以while就中止了,实际不是这样,因为JS是单线程的,所以进入while循环之后,没有「时间」(线程)去跑定时器了,所以这个代码跑起来是个死循环!

var 

事件循环是JavaScript实现异步的具体解决方案,其中同步代码直接执行;异步函数先放在异步队列中,待同步函数执行完毕后,轮循执行异步队列中的回调函数。

事件循环中,每进行一次循环操作称为tick,每一个tick的任务处理模型关键步骤如下:

  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的队列中
  • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,JS线程接续接管,开始下一个宏任务(从事件队列中获取)

0103926daeeeda6af6345f06a9dabdd5.png

(macro)task宏任务:包括script、setTimeout、I/O、UI交互等
micro task微任务:包括Promise.then、Mutation observer、process.nextTick(node.js环境等)。async/await和Promise实现延迟执行,并在每个task结束时执行。

在每一个事件循环之前,microtask队列总是被清空。

代码中出现setTimeout、async/await、Promise等函数正确的执行顺序是怎样的呢?

先看一道经典面试题目:

async 

控制台运行结果为:

script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

43bd7efaf0d7f36c07be7d3b0c6398e0.png

注:上图为Chrome75.0.3770.142执行结果截图,如果浏览器版本为Chrome61.0.3163.100(低于v73)则promise2先于async1 end打印(最新版本的firefox火狐亦是如此)。

7049dc7e40705394edc0d01223ee31ab.png

分析执行过程流程图:

"执行整体代码"开始后扫到task放入task queue,扫到微任务放入micro task queue。

f9abeb5fa82070aeb18ce5e9205c343d.png

分析要点主要记住3点:

(1)Promise中的异步体现在then和catch中,故写在Promise中的代码是被当做同步任务立即执行的;

(2)而在async/await中,在出现await之前其代码也是立即执行的。带async关键字的函数仅仅是把return值包装成promise返回,其他并无不同之处;

(3)await是让出线程的标志:await后面的表达式会先执行一遍(await等的是右侧表达式的结果),将await语句之后的代码加入到micro task中,然后就会跳出整个async函数来执行后续代码。


用上例方法来分析另一道例题:

例2:

setTimeout(() => console.log('setTimeout1'), 0);
setTimeout(() => {
    console.log('setTimeout2');
    Promise.resolve().then(() => {
        console.log('promise2');
        Promise.resolve().then(() => {
            console.log('promise3');
        })
        console.log(5)
    })
    setTimeout(() => console.log('setTimeout4'), 0);
}, 0);
setTimeout(() => console.log('setTimeout3'), 0);
Promise.resolve().then(() => {
    console.log('promise1');
})

ff495ae391e53d7c8e8157ac5e1c38f0.png

2796d166b3e874b20a7987a075db4ddc.png

最后,我们再来一道在node中的异步题目吧:

async 

(macro)task宏任务:包括script、setTimeout、I/O、UI交互、setImmediate(nodejs环境中)等 micro task微任务:包括Promise.then、Mutation observer、process.nextTick(node.js环境等)。async/await和Promise实现延迟执行,并在每个task结束时执行。在每一个事件循环之前,microtask队列总是被清空。

4f7d7421f9c40f8cda12cd63694fa7e4.png

windows下的node10.16.3运行结果如上图,Mac的node12.6.0运行结果稍有出入:

3c0bc0066937ba3b1ff68e5f71de6fc4.png

具体表现在 async1 end和promise3孰先孰后、setImmediate和setTimeout3孰先孰后的差异。

本文参考链接:

8张图让你一步步看清 async/await 和 promise 的执行顺序​segmentfault.com 浏览器和NodeJS中不同的Event Loop · Issue #234 · kaola-fed/blog​github.com
5230c35314aa53cfc0257b17efedcfc2.png
Tasks, microtasks, queues and schedules​jakearchibald.com
81c25c428e5f92d74aef6b2d5cd41813.png
更快的异步函数和 Promise​v8.js.cn 令人费解的 async/await 执行顺序​juejin.im 用一道大厂面试题带你搞懂事件循环机制​mp.weixin.qq.com
a48c1c68e75e7d7a086f42b7ae6dea59.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值