一、简介
javaScript是单线程非阻塞的脚本语言。
单线程
单线程是指在执行JavaScript代码的时候,主线程依照程序执行。
非阻塞
非阻塞是指执行异步工作的时候,主线程会挂起工作,期待异步工作返回后果后按程序执行
事件循环
同步工作:立刻执行的工作,同步工作个别会间接进入到主线程中执行
异步工作:异步执行的工作,异步工作又分为微工作(micorotask)和宏工作(macrotack)
同步工作进入主线程,即主执行栈,异步工作进入工作队列,主线程内的工作执行结束为空,会去工作队列读取对应的工作,推入主线程执行。上述过程的一直反复就是事件循环
二、宏工作与微工作
异步工作又分为微工作(micorotask)和宏工作(macrotack)
微工作
在以后宏工作执行完结之后立刻执行的工作,执行完微工作在执行下一个宏工作。
常见的微工作:Promise.then
Object.observe
MutationObserver
process.nextTick(ndoe环境)
宏工作
每次执行栈执行的工作就是宏工作(包含从工作队列中获取下一个宏工作队列去执行)。
常见的宏工作:script代码
setTimeout
setInterval
I/O
UI交互事件
postMessage
三、代码剖析
实例代码
console.log('script start')async function async1() { console.log('async1 start') await async2() console.log('async1 end') return 'async then'}async function async2() { console.log('async2 end')}async1()setTimeout(function() { console.log('setTimeout')}, 0)async1().then(function (message) { console.log(message) })new Promise(resolve => { console.log('Promise') resolve()}) .then(function() { console.log('promise1') }) .then(function() { console.log('promise2') })console.log('script end')
流程步骤
1、遇到console间接打印 'script start'
2、执行async1,打印console('async1 start'
),遇到await阻塞async2前面的流程。
3、执行async2,打印 'async2 end'
,async2前面的代码留着前面执行(工作队列:async1)
4、遇到定时器,属于新的宏工作,留着前面执行(工作队列:async1、定时器)
5、执行async1,打印出'async1 start'
、 'async2 end'
,
6、.then 属于微工作,放入微工作队列,前面再执行(工作队列:async1、then、定时器)
7、遇到 new Promise,这个是间接执行的,打印 'Promise'
8、.then 属于微工作,放入微工作队列,前面再执行(工作队列:async1、then(async1)、then(promise)、定时器)
9、遇到console间接打印 'script end'
执行工作队列宏工作(async1、then、then、定时器)
1、执行async2前面的代码,打印 'async1 end'
2、执行async1 async2前面的代码,打印 'async1 end'
,then放入微工作队列
3、执行promise 第一个then事件,打印 'promise1'
第二个then放入微工作队列
4、执行微工作队列async1 then事件,打印 'async then'
5、执行promise第二个then事件,打印 'promise2'
6、最初执行定时器 'setTimeout'
输入后果:
'script start''async1 start''async2 end''async1 start''async2 end''Promise''script end''async1 end''async1 end''promise1''async then''promise2''setTimeout'
四、参考文献
https://github.com/febobo/web...