Javascript中的异步/等待
在运行代码之前,我一直认为我理解了Javascript中的异步/等待,javascript,async-await,Javascript,Async Await,在运行代码之前,我一直认为我理解了async/await在Javascript中的工作原理: let flag = false; function test() { [1, 2, 3].map(async n => { console.log(`flag set at ${n} before if?`, flag); if (!flag) { const x = await a(n); // do something with x
async/await
在Javascript中的工作原理:
let flag = false;
function test() {
[1, 2, 3].map(async n => {
console.log(`flag set at ${n} before if?`, flag);
if (!flag) {
const x = await a(n);
// do something with x
flag = x;
console.log('flag set!');
}
console.log(`flag set at ${n} after if?`, flag);
});
}
function a(n) {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(n);
});
});
}
test();
实际输出为:
flag set at 1 before if? false
flag set at 2 before if? false
flag set at 3 before if? false
flag set!
flag set at 1 after if? 1
flag set!
flag set at 2 after if? 2
flag set!
flag set at 3 after if? 3
这和我想的很不一样:
flag set at 1 before if? false
flag set!
flag set at 1 after if? 1
flag set at 2 before if? 1
flag set at 2 after if? 1
flag set at 3 before if? 1
flag set at 3 after if? 1
我想我需要接受教育。谢谢
更新:
谢谢你对地图的评论。当我将代码更改为以下代码时,它按预期工作:
let flag = false;
async function test() {
for (const n of [1, 2, 3]) {
console.log(`flag set at ${n} before if?`, flag);
if (!flag) {
const x = await a(n);
// do something with x
flag = x;
console.log('flag set!');
}
console.log(`flag set at ${n} after if?`, flag);
}
}
function a(n) {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(n);
});
});
}
test();
wait
关键字确保当前方法线程在继续之前等待函数调用解析
这就是为什么每个标志都设置了代码>在日志之后的之前打印
但是,您的执行被封装在.map
中的异步箭头函数中。这意味着,即使箭头函数本身已暂停,.map
也不会暂停。正如@zerkms所提到的,它将你的阵列变成一个承诺阵列
将其视为对远程API的实际异步调用。您不需要等待服务器完成,来自.map
的所有调用都将完成,然后在返回每个初始值时进行计算
这正是这里发生的事情。map
并不等待,它只是将原始数组转换为承诺数组。对于顺序循环,请在等待
周围使用For of
map
只需调用回调函数三次,创建的三个承诺都是独立的。我很确定这与map的使用有关。如果要使用for循环,我认为不会有这种输出。@Andrew即使setTimeout
立即调用回调,它也不是同步的,而是在宏任务循环中,因此,在所有promise事件之后肯定会延迟。在没有第二个参数的情况下调用setTimeout仍然会与没有setTimeout完全不同,因为它将被放在浏览器异步事件队列的底部!我并不是说这个答案是错误的,但它的某些部分看起来有误导性,比如“不管你的执行是如何封装在arrow函数中的”。作为一个箭头函数意味着增加了问题。你有没有建议如何更好地表达它,这样就不会产生误导?英语不是我的第一语言,所以我可能不会总是正确地使用单词:(我用@zerkms解释改写了这篇文章,希望能把事情弄清楚。