了解知识点
- 线程
- 执行栈
- task queue
- web api
- macro task
- micro task
线程
Javascript是单线程的语言,
可以单线程将理解为只有一条车道,在车道里后面的车在等前面的车通过后,才能通过.
即当前面的程序没有执行,后面的程序也不能执行.
执行栈
执行栈像"车道",被执行的程序会放入执行栈里,
但它的执行的顺序是,后面进来的程序先执行.
示例
视频源地址
task queue
在线程中有很多等待运行的任务(程序,而执行栈只会放入一个任务.
其他可运行任务会放入任务队列中.
这里虽说是个队列, 它的执行的顺序,不会先进的程序先执行.
每个event loop都会有一个或多个任务队列
web api
Javascript是单线程,但也能实现异步,这种实现基与页面提供很多API,如(setTimeout, ajax, addEventListener ...)
这些都是异步函数,也就是说,运行到异步函数时,
把异步函数里闭包放入web api里,等待正确的时机,
web api会把闭包放入task queue里执行.
示例
macro task
macro task有setTimeout ,setInterval, setImmediate,requestAnimationFrame,I/O ,UI渲染...
task queue 是由很多个macro task组成的队列,
micro task
micro task有Promise, process.nextTick, Object.observe, MutationObserver...
每个event loop都会有一个micro task
event loop
执行流程
- 当执行栈为null时
- 看task queue的第一个macro task是不是null,如果不是取出放入执行栈,如果是跳转5
- 执行栈运行task
- 运行完毕,把task设置null,并移出
- 执行 micro task队列
a. 看micro task队列第一task个是不是null,如果不是取出放入执行栈,如果是跳转f
b. 执行栈运行task
c. 运行完毕,把task设置null,并移出
d. 看micro task队列下一个task是不是null,如果不是跳转b
f. 结束micro task队列执行 - 跳转到1
示例
实战
猜想
在macro/micro task 进入执行栈时,中间应该会有一个缓存区,
例如
如果是把整个macro task放入执行栈,
按后进程序先执行的机制, 应该会先打印'b',
但打印的是'a',说明函数b是等函数a执行完后再进入执行栈的,
所以在macro task 会把里面的函数拆分为一个执行的队列,放入执行栈里.
示例
参考资料
https://github.com/ccforward/cc/issues/48
https://juejin.im/entry/596d78ee6fb9a06bb752475c
Make a friend
作者有一年半的前端开发经验,比较擅长性能优化和vue,喜欢对各种原理的深究,
喜欢篮球和电影
如果有趣味相投可以加入微信群