当前位置:   article > 正文

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

js中调用含有return的函数不能停止运行

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 

控制台运行结果为:

  1. script start
  2. async1 start
  3. async2
  4. promise1
  5. script end
  6. async1 end
  7. promise2
  8. 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:

  1. setTimeout(() => console.log('setTimeout1'), 0);
  2. setTimeout(() => {
  3. console.log('setTimeout2');
  4. Promise.resolve().then(() => {
  5. console.log('promise2');
  6. Promise.resolve().then(() => {
  7. console.log('promise3');
  8. })
  9. console.log(5)
  10. })
  11. setTimeout(() => console.log('setTimeout4'), 0);
  12. }, 0);
  13. setTimeout(() => console.log('setTimeout3'), 0);
  14. Promise.resolve().then(() => {
  15. console.log('promise1');
  16. })

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
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/227786
推荐阅读
相关标签
  

闽ICP备14008679号