跳到主要内容

任务队列

2023年06月17日
柏拉文
越努力,越幸运

一、async


async 函数返回一个 Promise 对象。async函数在抛出返回值时,会根据返回值类型开启不同数目的微任务

1.1 return 普通数据

return 普通数据: 对应回调直接加入到微任务队列。

function x() {
console.log(0);
return new Promise(resolve => {
console.log(1);
resolve(2);
console.log(3);
});
}

async function y() {
console.log(4);
const result = await x();
console.log(result);
return 5;
}

y()
.then(res => {
console.log(res);
})
.catch(error => {
console.log(error);
});

new Promise(resolve => {
console.log(6);
resolve();
console.log(8);
})
.then(() => {
console.log(9);
})
.then(() => {
console.log(10);
})
.then(() => {
console.log(11);
})
.then(() => {
console.log(12);
});

/**
* @description: 执行过程
* macrosTack[] microTask[]
* 1. 同步执行 y
* 2. 执行 console.log(4); , 输出 4
* 3. 同步执行 const result = await x();
* 4. 进入 x
* 5. 同步执行 console.log(0);, 输出 0
* 6. 同步执行 return new Promise
* 7. 同步执行 console.log(1); , 输出 1
* 8. 同步执行 resolve(2); ,将 y() 函数内部 await 之后的代码作为一个微任务加入 microTask 队列。 此时 microTask = [(console.log(result); return 5;)]
* 9. 同步执行 console.log(3); , 输出 3
* 10. 同步执行 new Promise
* 11. 同步执行 console.log(6); , 输出 6
* 12. 同步执行 resolve(); 将第一个 .then 加入到 microTask 队列。 此时 microTask = [(console.log(result); return 5;), console.log(9);]
* 13. 同步执行 console.log(8); , 输出 8
* 14. 开始清空 microTask 队列
* 15. 执行 console.log(result), 输出 2
* 16. 执行 return 5, 将 y 的第一个 .then() 加入到 microTask 队列。 此时 microTask = [console.log(9);, console.log(res);]
* 17. 执行 console.log(9), 输出 9。将 new Promise 的第二个 .then 加入到 microTask 队列。 此时 microTask = [console.log(res); console.log(10);]
* 18. 执行 console.log(res), 输出 5。
* ……
* 因此,最终结果为: 4 0 1 3 6 8 2 9 5 10 11 12
*/

1.2 return thenable

return thenable: 对应回调与之前的微任务隔一个加入到微任务队列。相当于 microTask = [之前的微任务……, 空一个, thenable 回调]

function x() {
console.log(0);
return new Promise(resolve => {
console.log(1);
resolve(2);
console.log(3);
});
}

async function y() {
console.log(4);
const result = await x();
console.log(result);
return {
then(cb) {
cb(5);
}
};
}

y()
.then(res => {
console.log(res);
})
.catch(error => {
console.log(error);
});

new Promise(resolve => {
console.log(6);
resolve();
console.log(8);
})
.then(() => {
console.log(9);
})
.then(() => {
console.log(10);
})
.then(() => {
console.log(11);
})
.then(() => {
console.log(12);
});

/**
* @description: 执行过程
* macrosTack[] microTask[]
* 1. 同步执行 y
* 2. 执行 console.log(4); , 输出 4
* 3. 同步执行 const result = await x();
* 4. 进入 x
* 5. 同步执行 console.log(0);, 输出 0
* 6. 同步执行 return new Promise
* 7. 同步执行 console.log(1); , 输出 1
* 8. 同步执行 resolve(2); ,将 y() 函数内部 await 之后的代码作为一个微任务加入 microTask 队列。 此时 microTask = [(console.log(result); return thenable;)]
* 9. 同步执行 console.log(3); , 输出 3
* 10. 同步执行 new Promise
* 11. 同步执行 console.log(6); , 输出 6
* 12. 同步执行 resolve(); 将第一个 .then 加入到 microTask 队列。 此时 microTask = [(console.log(result); return thenable;), console.log(9);]
* 13. 同步执行 console.log(8); , 输出 8
* 14. 开始清空 microTask 队列
* 15. 执行 console.log(result), 输出 2
* 16. 执行 return thenable;, 将 y 的第一个 .then() 回调加入空一个加入到 microTask 队列。 此时 microTask = [console.log(9);, 空一个 , console.log(res);]
* 17. 执行 console.log(9), 输出 9。将 new Promise 的第二个 .then 加入到 microTask 队列。 此时 microTask = [console.log(10);, console.log(res);]
* 18. 执行 console.log(10), 输出 10。 将 new Promise 的第三个 .thn 加入到 microTask 队列. 此时 microTask = [console.log(res);,console.log(11);]
* 19. 执行 console.log(res);, 输出 5
* 20. ……
* 因此,最终结果为: 4 0 1 3 6 8 2 9 10 5 11 12
*/

那么,假如说, 在 y() 后面再加一个 .then 呢? 结果是怎样的?

function x() {
console.log(0);
return new Promise(resolve => {
console.log(1);
resolve(2);
console.log(3);
});
}

async function y() {
console.log(4);
const result = await x();
console.log(result);
// return 5;
// return new Promise(resolve => {
// resolve(5);
// });
return {
then(cb) {
cb(5);
}
};
}

y()
.then(res => {
console.log(res);
})
.then(() => {
console.log(13);
})
.catch(error => {
console.log(error);
});

new Promise(resolve => {
console.log(6);
resolve();
console.log(8);
})
.then(() => {
console.log(9);
})
.then(() => {
console.log(10);
})
.then(() => {
console.log(11);
})
.then(() => {
console.log(12);
});

/**
* @description: 执行过程
* macrosTack[] microTask[]
* 1. 同步执行 y
* 2. 执行 console.log(4); , 输出 4
* 3. 同步执行 const result = await x();
* 4. 进入 x
* 5. 同步执行 console.log(0);, 输出 0
* 6. 同步执行 return new Promise
* 7. 同步执行 console.log(1); , 输出 1
* 8. 同步执行 resolve(2); ,将 y() 函数内部 await 之后的代码作为一个微任务加入 microTask 队列。 此时 microTask = [(console.log(result); return thenable;)]
* 9. 同步执行 console.log(3); , 输出 3
* 10. 同步执行 new Promise
* 11. 同步执行 console.log(6); , 输出 6
* 12. 同步执行 resolve(); 将第一个 .then 加入到 microTask 队列。 此时 microTask = [(console.log(result); return thenable;), console.log(9);]
* 13. 同步执行 console.log(8); , 输出 8
* 14. 开始清空 microTask 队列
* 15. 执行 console.log(result), 输出 2
* 16. 执行 return thenable;, 将 y 的第一个 .then() 回调加入空一个加入到 microTask 队列。 此时 microTask = [console.log(9);, 空一个 , console.log(res);]
* 17. 执行 console.log(9), 输出 9。将 new Promise 的第二个 .then 加入到 microTask 队列。 此时 microTask = [console.log(10);, console.log(res);]
* 18. 执行 console.log(10), 输出 10。 将 new Promise 的第三个 .then 加入到 microTask 队列. 此时 microTask = [console.log(res);,console.log(11);]
* 19. 执行 console.log(res);, 输出 5 , 将 y 的第二个 .then 加入到 microTask 队列。 此时, microTask = [console.log(11);,console.log(13);]
* 20. 执行 console.log(11);, 输出 11 , 将 new Promise 的第四个 .then 加入到 microTask 队列。 此时 microTask = [console.log(13);,console.log(12);]
* 因此,最终结果为: 4 0 1 3 6 8 2 9 10 5 11 13 12
*/

1.3 return new Promise

return Promise: 对应回调与之前的微任务隔两个加入到微任务队列。相当于 microTask = [之前的微任务……, 空一个, 空一个, .then 回调]

function x() {
console.log(0);
return new Promise(resolve => {
console.log(1);
resolve(2);
console.log(3);
});
}

async function y() {
console.log(4);
const result = await x();
console.log(result);
return new Promise(resolve => {
resolve(5);
});
}

y()
.then(res => {
console.log(res);
})
.catch(error => {
console.log(error);
});

new Promise(resolve => {
console.log(6);
resolve();
console.log(8);
})
.then(() => {
console.log(9);
})
.then(() => {
console.log(10);
})
.then(() => {
console.log(11);
})
.then(() => {
console.log(12);
});

/**
* @description: 执行过程
* macrosTack[] microTask[]
* 1. 同步执行 y
* 2. 执行 console.log(4); , 输出 4
* 3. 同步执行 const result = await x();
* 4. 进入 x
* 5. 同步执行 console.log(0);, 输出 0
* 6. 同步执行 return new Promise
* 7. 同步执行 console.log(1); , 输出 1
* 8. 同步执行 resolve(2); ,将 y() 函数内部 await 之后的代码作为一个微任务加入 microTask 队列。 此时 microTask = [(console.log(result); return new Promise;)]
* 9. 同步执行 console.log(3); , 输出 3
* 10. 同步执行 new Promise
* 11. 同步执行 console.log(6); , 输出 6
* 12. 同步执行 resolve(); 将第一个 .then 加入到 microTask 队列。 此时 microTask = [(console.log(result); return new Promise;), console.log(9);]
* 13. 同步执行 console.log(8); , 输出 8
* 14. 开始清空 microTask 队列
* 15. 执行 console.log(result), 输出 2
* 16. 执行 return new Promise;, 将 y 的第一个 .then() 回调空两个加入到 microTask 队列。 此时 microTask = [console.log(9);, 空一个 ,空一个, console.log(res);]
* 17. 执行 console.log(9), 输出 9。将 new Promise 的第二个 .then 加入到 microTask 队列。 此时 microTask = [console.log(10);, 空一个, console.log(res);]
* 18. 执行 console.log(10), 输出 10。 将 new Promise 的第三个 .then 加入到 microTask 队列. 此时 microTask = [console.log(11);console.log(res);]
* 19. 执行 console.log(11), 输出 11。将 new Promise 的第四个 .then 加入到 microTask 队列, 此时 microTask = [console.log(res););, console.log(12);]
* 20. 执行 console.log(res);), 输出 5
* 因此,最终结果为: 4 0 1 3 6 8 2 9 10 11 5 12
*/

那么,假如说, 在 y() 后面再加一个 .then 呢? 结果是怎样的?

function x() {
console.log(0);
return new Promise(resolve => {
console.log(1);
resolve(2);
console.log(3);
});
}

async function y() {
console.log(4);
const result = await x();
console.log(result);
return new Promise(resolve => {
resolve(5);
});
}

y()
.then(res => {
console.log(res);
})
.then(() => {
console.log(13);
})
.catch(error => {
console.log(error);
});

new Promise(resolve => {
console.log(6);
resolve();
console.log(8);
})
.then(() => {
console.log(9);
})
.then(() => {
console.log(10);
})
.then(() => {
console.log(11);
})
.then(() => {
console.log(12);
});

/**
* @description: 执行过程
* macrosTack[] microTask[]
* 1. 同步执行 y
* 2. 执行 console.log(4); , 输出 4
* 3. 同步执行 const result = await x();
* 4. 进入 x
* 5. 同步执行 console.log(0);, 输出 0
* 6. 同步执行 return new Promise
* 7. 同步执行 console.log(1); , 输出 1
* 8. 同步执行 resolve(2); ,将 y() 函数内部 await 之后的代码作为一个微任务加入 microTask 队列。 此时 microTask = [(console.log(result); return new Promise;)]
* 9. 同步执行 console.log(3); , 输出 3
* 10. 同步执行 new Promise
* 11. 同步执行 console.log(6); , 输出 6
* 12. 同步执行 resolve(); 将第一个 .then 加入到 microTask 队列。 此时 microTask = [(console.log(result); return new Promise;), console.log(9);]
* 13. 同步执行 console.log(8); , 输出 8
* 14. 开始清空 microTask 队列
* 15. 执行 console.log(result), 输出 2
* 16. 执行 return new Promise;, 将 y 的第一个 .then() 回调空两个加入到 microTask 队列。 此时 microTask = [console.log(9);, 空一个 ,空一个, console.log(res);]
* 17. 执行 console.log(9), 输出 9。将 new Promise 的第二个 .then 加入到 microTask 队列。 此时 microTask = [console.log(10);, 空一个, console.log(res);]
* 18. 执行 console.log(10), 输出 10。 将 new Promise 的第三个 .then 加入到 microTask 队列. 此时 microTask = [console.log(11);console.log(res);]
* 19. 执行 console.log(11), 输出 11。将 new Promise 的第四个 .then 加入到 microTask 队列, 此时 microTask = [console.log(res););, console.log(12);]
* 20. 执行 console.log(res);), 输出 5 , 将 y 的第二个 .then 加入到 microTask 队列, 此时 microTask = [console.log(12);console.log(13);]
* 因此,最终结果为: 4 0 1 3 6 8 2 9 10 11 5 12 13
*/

二、await


2.1 await 普通数据

await 普通数据: await 之后的代码直接加入到微任务队列。

async function x() {
console.log(1);
await 2;
console.log(3);
}

x();

new Promise(resolve => {
console.log(4);
resolve();
console.log(5);
})
.then(() => {
console.log(6);
})
.then(() => {
console.log(7);
})
.then(() => {
console.log(8);
})
.then(() => {
console.log(9);
});

/**
* @description: 执行过程
*/

2.2 await thenable

return thenable: await 之后的代码与之前的微任务隔一个加入到微任务队列。相当于 microTask = [之前的微任务……, 空一个, await 之后的代码]

async function x() {
console.log(1);
await {
then(cb) {
cb(2);
}
};
console.log(3);
}

x();

new Promise(resolve => {
console.log(4);
resolve();
console.log(5);
})
.then(() => {
console.log(6);
})
.then(() => {
console.log(7);
})
.then(() => {
console.log(8);
})
.then(() => {
console.log(9);
});

/**
* @description: 执行过程
*/

2.3 await new Promise

await new Promise: await 之后的代码直接加入到微任务队列。

async function x() {
console.log(1);
await new Promise(resolve => {
resolve(2);
});
console.log(3);
}

x();

new Promise(resolve => {
console.log(4);
resolve();
console.log(5);
})
.then(() => {
console.log(6);
})
.then(() => {
console.log(7);
})
.then(() => {
console.log(8);
})
.then(() => {
console.log(9);
});

/**
* @description: 执行过程
*/

2.4 await async function

await async function 相当于 async function.then().then() , await 之后的代码就是 .then() 的回调, 加入到微任务队列的机制同理。