javascript - Javascript 中的异步/等待
问题描述
在我运行代码之前,我以为我理解了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();
解决方案
await
关键字确保当前方法线程在继续之前等待函数调用解决。
这就是为什么每个人都在日志flag set!
之前打印。after
但是,您的执行被封装在.map
. 这意味着,即使箭头函数本身被暂停,.map
也不会。正如@zerkms 所提到的,它将您的数组变成了一系列承诺。
将其视为对远程 API 的实际异步调用。您不会等待服务器完成,所有来自 的调用.map
都将完成,然后在它们返回时针对每个初始值进行评估。
这正是这里正在发生的事情。
推荐阅读
- kubernetes - Kuberenes - 具有集群管理员的服务帐户无法访问命名空间
- go - 在 Kubernetes 集群中移动 Pod 作为部署的一部分
- android-sqlite - 对于不使用 SQLite 的应用程序,android.database.sqlite.SQLiteCantOpenDatabaseException 的可能来源是什么
- javascript - 有没有更简单的方法在 JS 中应用实时选择?
- python - 如何将图像从 url 下载到这个自定义 ImageField(JsonField) Django
- c++ - 按升序排列数组
- terraform - terraform:如何覆盖 AWS RDS 最终快照
- git - 如何撤消 git add* git stash git pull?
- java - Java 变量值在响应请求后保留在内存中
- android - 如何旋转矩阵?