例子一
setTimeout(function() {console.log('setTimeout');
})
new Promise(function(resolve) {console.log('promise');
}).then(function() {console.log('then');
})
console.log('console');
- 整段代码做为宏工作,进入主线程
- 遇到
setTimeout
,将其回调函数注册后散发到宏工作事件队列中(作为下一次循环宏工作调用) - 接下来遇到了
Promise
,new Promise
立刻执行,打印 ’promise’,then
函数散发到微工作事件队列(本次宏工作的微工作) - 遇到
console.log()
,立刻执行 - 整体代码作为第一次循环的宏工作执行完结,查看还有微工作
then
,执行 - 开始第二次循环,执行
setTimeout
,打印 ’promise’ - 后果:promise, console, then, setTimeout
例子二
console.log('Hello World!');
const p1 = new Promise((resolve) => {console.log(3);
resolve(4);
});
const p2 = new Promise((resolve) => {console.log(1);
setTimeout(() => {console.log(6)
}, 0);
resolve(2);
});
p1.then((res) => {console.log(res)
});
p2.then((res) => {console.log(res)
});
console.log(5);
- 整体代码作为宏工作进入主线程,先执行打印 ’hello world’
- 而后
p1
中打印 ’3’,resolve(4)
在then
函数中散发到微工作事件队列 - 而后进入
p2
中打印 ’1’,遇到setTimeout
,将其回调函数注册散发到宏工作事件队列 resolve(2)
在then
函数中散发到微工作事件队列;向下执行,再打印 ’5′- 第一次循环的宏工作执行完,查看微工作事件队列,先打印 ’4’,再打印 ’2′
- 第二次循环,执行宏工作中的
setTimeout
,打印 ’6′ - 后果:hello world,3,1,5,4,2,6
例子三
console.log('1');
setTimeout(function first () {console.log('2');
setTimeout(function third () {new Promise(function(resolve) {console.log('3');
resolve();}).then(function() {console.log('4')
})
})
})
new Promise(function(resolve) {console.log('5');
resolve();}).then(function() {console.log('6')
})
setTimeout(function second () {console.log('7');
new Promise(function(resolve) {console.log('8');
resolve();}).then(function() {console.log('9')
})
})
- 整体代码作为第一次宏工作,进入主线程执行,先打印 ’1’,再将
setTimeout
的回调函数first
注册散发到宏工作事件队列 - 向下执行,进入
Promise
中打印 ’5’,then
函数散发到微工作事件队列 - 再遇到一个
setTimeout
,将其回调函数second
注册散发到宏工作事件队列中 - 第一次循环的宏工作实现,执行微工作的
then
函数,打印 ’6′ - 开始第二次循环,执行宏工作队列中的
first
函数打印 ’2’;而后又遇到了setTimeout
函数,将third
函数注册散发到宏工作事件队列中(下次循环才会调用) - 接着,执行本次宏工作队列中的
second
函数打印 ’7’,进入promise
打印 ’8’,then
函数注册散发到微工作事件队列 - 第二次循环的宏工作实现,执行微工作的
then
函数,打印 ’9′ - 开始第三次循环,执行宏工作队列中
third
函数,先打印 ’3’,再执行then
中打印 ’4′ - 后果:1,5,6,2,7,8,9,3,4
总结
- 所有的同步工作都在主线程上执行,造成一个执行栈
- 主线程之外,还存在一个工作队列,只有异步工作有了运行后果,就在工作队列中搁置一个事件
- 一旦执行栈中所有同步工作执行结束,零碎就会读取工作队列中的事件,异步工作完结期待状态,进入执行栈,开始执行
- 反复上一步(事件轮循——反复读取主线程和工作队列中的事件)
-
在 js 中的工作做更准确的定义:
- macro-task(宏工作): 整体代码 js,setTimeout,setInterval
- micro-task(微工作): Promise.then,process.nextTick(node.js)
- 在本次循环执行中,先执行宏工作,再执行微工作,都实现后,开始第二轮循环,执行宏工作,执行微工作,直到没有宏工作,实现执行
- 图片起源