事件循环
要点
异步任务先注册再执行。尤须注意
Promise多个then时微任务的注册顺序then微任务注册时机。碰到then时再注册,而非一看到resolve就立即注册,resolve仅是确保该then微任务能够被注册遇到
await,会立即执行右边的语句,然后提前跳出async函数,待外部执行完毕后,再返回async函数内部继续执行未执行完的
习题 1
console.log('start')
setTimeout(() => {
console.log('children2')
Promise.resolve().then(() => {
console.log('children3')
})
}, 0)
new Promise(function(resolve, reject) {
console.log('children4')
setTimeout(function() {
console.log('children5')
resolve('children6')
}, 0)
}).then(res =>{
console.log('children7')
setTimeout(() => {
console.log(res)
}, 0)
})
// 输出
start
children4
children2
children3
children5
children7
children6
习题 2 hard
setTimeout(() => { // 宏 1
console.log(0)
})
new Promise(resolve => {
resolve()
Promise.resolve().then(() => { // 微 1
console.log(2)
Promise.resolve().then(() => { // 微 3
console.log(4)
})
})
console.log(3)
}).then(() => { // 微 2
console.log(1)
})
console.log(5)
// 输出
3、5、2、1、4、0
// 解析
script 整体作为一个宏任务开始执行
碰到 setTimeout,注册宏 1
碰到第一个 then,注册微 1
继续执行同步代码,输出 3
碰到第二个 then,注册微 2
继续执行同步代码,输出 5
script 整体宏任务执行完毕,检查微任务队列不为空,准备逐一执行
取出微 1,输出 2
碰到第三个 then,注册微 3
取出微 2,输出 1
取出微 3,输出 4
当前微任务队列所有微任务执行完毕,准备执行下一个宏任务
取出宏 1,输出 0
宏 1 执行完毕,检查微任务队列为空,则准备执行下一个宏任务,检查宏任务队列也为空,则事件循环结束
习题 3
console.log(1)
setTimeout(() => { // 宏 1
console.log(2)
Promise.resolve().then(() => { 微 4
console.log(3)
})
})
new Promise((resolve, reject) => {
console.log(4)
resolve(5)
}).then((data) => { // 微 1
console.log(data)
Promise.resolve().then(() => { // 微 2
console.log(6)
}).then(() => { // 微 3
console.log(7)
setTimeout(() => { // 宏 3
console.log(8)
}, 0)
})
})
setTimeout(() => { // 宏 2
console.log(9)
})
console.log(10)
// 输出
1、4、10、5、6、7、2、3、9、8
// 解析
script 整体作为一个宏任务开始执行
执行同步代码,输出 1
碰到第一个 setTimeout,注册宏 1
继续执行同步代码,输出 4
碰到第一个 then,注册微 1
碰到第二个 setTimeout,注册宏 2
继续执行同步代码,输出 10
script 整体宏任务执行完毕,检查微任务队列不为空,准备逐一执行
取出微 1,输出 5
碰到第二个 then,注册微 2
取出微 2,输出 6
碰到第三个 then,注册微 3
取出微 3,输出 7
碰到第三个宏任务,注册宏 3
当前微任务队列所有微任务执行完毕,准备执行下一个宏任务
取出宏 1,输出 2
碰到第四个微任务,注册微 4
宏 1 执行完毕,检查微任务队列不为空,准备逐一执行
取出微 4,输出 3
当前微任务队列所有微任务执行完毕,准备执行下一个宏任务
取出宏 2,输出 9
宏 2 执行完毕,检查微任务队列为空,则准备执行下一个宏任务,检查宏任务队列不为空
取出宏 3,输出 8
宏 3 执行完毕,检查微任务队列为空,则准备执行下一个宏任务,检查宏任务队列也为空,则事件循环结束
习题 4 hard
var myPromise = Promise.resolve(Promise.resolve('Promise'))
function funcOne() {
console.log('funcOne Start')
myPromise.then(res => res).then(res => console.log('funcOne ' + res))
setTimeout(() => console.log('funcOne Timeout'), 0)
console.log('funcOne End')
}
async function funcTwo() {
console.log('funcTwo Start')
const res = await myPromise
console.log(await 'funcTwo ' + res)
setTimeout(() => console.log('funcTwo Timeout'), 0)
console.log('funcTwo End')
}
funcOne()
funcTwo()
// 输出
funcOne Start
funcOne End
funcTwo Start
funcOne Promise
funcTwo Promise
funcTwo End
funcOne Timeout
funcTwo Timeout
习题组 1
习题一
new Promise((resolve, reject) => {
console.log('外部 promise')
resolve()
}).then(() => {
console.log('外部第一个 then')
return new Promise((resolve, reject) => {
console.log('内部 promise')
resolve()
}).then(() => {
console.log('内部第一个 then')
}).then(() => {
console.log('内部第二个 then')
})
}).then(() => {
console.log('外部第二个 then')
})
// 输出
外部 promise
外部第一个 then
内部 promise
内部第一个 then
内部第二个 then
外部第二个 then
习题二
new Promise((resolve, reject) => {
console.log('外部 promise')
resolve()
}).then(() => {
console.log('外部第一个 then')
new Promise((resolve, reject) => {
console.log('内部 promise')
resolve()
}).then(() => {
console.log('内部第一个 then')
}).then(() => {
console.log('内部第二个 then')
})
}).then(() => {
console.log('外部第二个 then')
})
// 输出
外部 promise
外部第一个 then
内部 promise
内部第一个 then
外部第二个 then
内部第二个 then
习题三
new Promise((resolve, reject) => {
console.log('外部 promise')
resolve()
}).then(() => {
console.log('外部第一个 then')
let p = new Promise((resolve, reject) => {
console.log('内部 promise')
resolve()
})
p.then(() => {
console.log('内部第一个 then')
})
p.then(() => {
console.log('内部第二个 then')
})
}).then(() => {
console.log('外部第二个 then')
})
// 输出
外部 promise
外部第一个 then
内部 promise
内部第一个 then
内部第二个 then
外部第二个 then
习题四 hard
let p = new Promise((resolve, reject) => {
console.log('外部 promise')
resolve()
})
p.then(() => {
console.log('外部第一个 then')
new Promise((resolve, reject) => {
console.log('内部 promise')
resolve()
}).then(() => {
console.log('内部第一个 then')
}).then(() => {
console.log('内部第二个 then')
})
})
p.then(() => {
console.log('外部第二个 then')
})
// 输出
外部 promise
外部第一个 then
内部 promise
外部第二个 then
内部第一个 then
内部第二个 then
习题五 hard
new Promise((resolve, reject) => {
console.log('外部 promise')
resolve()
}).then(() => {
console.log('外部第一个 then')
new Promise((resolve, reject) => {
console.log('内部 promise')
resolve()
}).then(() => {
console.log('内部第一个 then')
}).then(() => {
console.log('内部第二个 then')
})
return new Promise((resolve, reject) => {
console.log('内部 promise2')
resolve()
}).then(() => {
console.log('内部第一个 then2')
}).then(() => {
console.log('内部第二个 then2')
})
}).then(() => {
console.log('外部第二个 then')
})
// 输出
外部 promise
外部第一个 then
内部 promise
内部 promise2
内部第一个 then
内部第一个 then2
内部第二个 then
内部第二个 then2
外部第二个 then
习题组 2
习题一
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout')
}, 0)
async1()
new Promise((resolve) => {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
})
console.log('script end')
// 输出
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
习题二
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
})
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout')
}, 0)
async1()
new Promise(function (resolve) {
console.log('promise3')
resolve()
}).then(function () {
console.log('promise4')
})
console.log('script end')
// 输出
script start
async1 start
promise1
promise3
script end
promise2
async1 end
promise4
setTimeout
习题三 hard
async function async1() {
console.log('async1 start')
await async2()
setTimeout(function() {
console.log('setTimeout1')
}, 0)
}
async function async2() {
setTimeout(function() {
console.log('setTimeout2')
}, 0)
}
console.log('script start')
setTimeout(function() {
console.log('setTimeout3')
}, 0)
async1()
new Promise(function(resolve) {
console.log('promise1')
resolve()
}).then(function() {
console.log('promise2')
})
console.log('script end')
// 输出
script start
async1 start
promise1
script end
promise2
setTimeout3
setTimeout2
setTimeout1