关于 async await
async/await被称为JS中异步终极解决方案。它既能够用同步的方式来书写异步代码,又得到底层的语法支持,无需借助任何第三方库。
Promise 核心思想:Promise 的 then 的注册微任务队列和执行是分离的。
注册 => 完全遵循 JS 和 Promise 的代码的执行过程。
执行 => 先同步,再微任务,再宏任务。
forEach 中用 await 产生的异步问题
举个 🌰:
async function test() {
let arr = [4, 2, 1];
arr.forEach(async (item) => {
const res = await handle(item);
console.log(res);
});
console.log('结束');
}
function handle(x) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(x);
}, 1000 * x);
});
}
test();
// 期望输出:
// 4
// 2
// 1
// 结束
// 实际输出:
// 结束
// 1
// 2
// 4
利用for...of就能轻松解决
async function test1() {
let arr = [4, 2, 1];
for (const item of arr) {
const res = await handle(item);
console.log(res);
}
console.log('结束');
}
// 4
// 2
// 1
// 结束
原理——Iterator
for...of 并不像 forEach 那么简单粗暴的方式去遍历执行,而是采用一种特别的手段——
迭代器去遍历。
对于数组来讲,它是一种可迭代数据类型——原生具有[Symbol.iterator]属性数据类型为可迭代数据类型,如数组、类数组(如 arguments、NodeList)、Set 和 Map。
可迭代对象可以通过迭代器进行遍历:
let arr = [4, 2, 1];
// 这就是迭代器
let iterator = arr[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
// {value: 4, done: false}
// {value: 2, done: false}
// {value: 1, done: false}
// {value: undefined, done: true}
async function test() {
let arr = [4, 2, 1];
let iterator = arr[Symbol.iterator]();
let res = iterator.next();
while (!res.done) {
let value = res.value;
console.log(value);
await handle(value);
res = iterator.next();
}
console.log('结束');
}
// 4
// 2
// 1
// 结束