浏览器是多线程的。 JS是单线程:浏览器只给了其中一个进程来渲染,但浏览器又提供了事件队列(Event Queue)来处理异步任务。事件队列中又包括了微任务与宏任务。浏览器会先执行微任务,再执行宏任务。
宏任务
- 定时器
- 事件绑定
- ajax
微任务
- async
- awiat
- promise中的resolve() / reject()
同步任务
- new promise
async function async1() {
console.log('async1 start')
await async2() // await后面的代码会放入微任务队列中
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout')
}, 0)
async1()
new Promise(function (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
//3 7 4 1 2 5
const first = () => (new Promise((resolve, reject) => {
console.log(3)
let p = new Promise((resolve, reject) => {
console.log(7)
setTimeout(() => {
console.log(5)
resolve(6) //会被忽略,因为会先执行微队列里的resolve(1),此时状态已经改变过了,且状态只能改变一次
}, 0)
resolve(1)
})
resolve(2)
p.then((arg) => {
console.log(arg)
})
}))
first().then((arg) => {
console.log(arg)
})
console.log(4)
// 1, 7, 2, 3,8,4, 6, 5, 0
setTimeout(() => {
console.log("0")
}, 0)
new Promise((resolve, reject) => {
console.log("1")
resolve()
}).then(() => {
console.log("2")
new Promise((resolve, reject) => {
console.log("3")
resolve()
}).then(() => {
console.log("4")
}).then(() => {
console.log("5")
})
}).then(() => {
console.log("6")
})
new Promise((resolve, reject) => {
console.log("7")
resolve()
}).then(() => {
console.log("8")
})
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end')
}
async function async2() {
console.log('async2 start')
return new Promise((resolve, reject) => {
resolve()
console.log('async2 promise')
})
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout')
}, 0)
async1()
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
}).then(function () {
console.log('promise3')
})
// script start, async1 start, async2 start, async2 promise, promise1
// promise2, promise3, async1 end?
// setTimeout
2022.10,17补充
- 调用栈:后进先出。放的是要执行的代码。
- 定时器:间隔一段时间后,将函数放入到
任务队列中 - Promise在执行,then就相当于给Promise了回调函数。当Promise的状态从pending变为fulfilled时,then的回调函数就会被放入
任务队列中 - 任务队列分为两种:
- 宏任务队列:
- 微任务队列:Promise的回调函数(then、catch、finally)。queueMicrotash()用来向微任务队列中添加一个任务。
- 执行流程
-
- 先执行调用栈的所有
-
- 中兴所有的微任务队列
-
- 执行宏任务队列
-