1.for中使用
const skills = ["js", "vue", "node", "react"];
function getSkillPromise(value) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(value);
}, 1000);
});
}
async function test() {
for (let i = 0; i < skills.length; i++) {
const skill = skills[i];
const res = await getSkillPromise(skill);
console.log(res);
}
}
test(); // 调用
当使用await时,希望JavaScript暂停执行,直到等待 promise 返回处理结果。上述结果意味着for循环中有异步代码,是可以等到for循环中异步代码完全跑完之后再执行for循环后面的代码。
但是他不能处理回调的循环,如forEach、map、filter等,下面具体分析。
2.map中使用
在map中使用await, map 的返回值始是promise数组,这是因为异步函数总是返回promise。
async function test() {
console.log("start");
const res = skills.map(async item => {
return await getSkillPromise(item);
});
console.log(res);
console.log("end");
}
test();
结果:始终为promise数组
start
[
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> }
]
end
若果你想要等到promise的返回结果,可以使用promise.all()处理一下
async function test() {
console.log("start");
const res = skills.map(async item => {
return await getSkillPromise(item);
});
const resPromise = await Promise.all(res);
console.log(resPromise);
console.log("end");
}
test();
// 结果
start[("js", "vue", "node", "react")];
end;
3.forEach中使用
先上代码
async function test() {
console.log("start");
skills.forEach(async item => {
const res = await getSkillPromise(item);
console.log(res);
});
console.log("end");
}
test();
预期结果
"Start";
"js";
"vue";
"node";
"react";
"End";
实际结果 在forEach循环等待异步结果返回之前就执行了console.log(‘end’)
"Start";
"End";
"js";
"vue";
"node";
"react";
JavaScript 中的 forEach不支持 promise 感知,也不支持 async 和await,所以不能在 forEach 使用 await 。
4.filter中使用
正常使用 filter:
async function test() {
console.log("start");
const res = skills.filter(item => {
return ["vue", "react"].includes(item);
});
console.log(res);
console.log("end");
}
test(); // 调用
// 结果
start[("vue", "react")];
end;
使用 await后:
async function test() {
console.log("start");
const res = skills.filter(async item => {
const skill = await getSkillPromise(item);
return ["vue", "react"].includes(item);
});
console.log(res);
console.log("end");
}
test();
预期结果:
start[("vue", "react")];
end;
实际结果:
start[("js", "vue", "node", "react")];
end;
结论:因为异步函数getSkillPromise返回结果返回的promise总是真的,所以所有选项都通过了过滤
小结
如果你想连续执行await调用,请使用for循环(或任何没有回调的循环)。
永远不要和forEach一起使用await,而是使用for循环(或任何没有回调的循环)。
不要在 filter 和 reduce 中使用 await,如果需要,先用 map 进一步骤处理,然后在使用 filter 和 reduce 进行处理。