首页 > 解决方案 > Javascript 中的异步/等待

问题描述

在我运行代码之前,我以为我理解了async/awaitJavascript 的工作原理:

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();

标签: javascriptasync-await

解决方案


await关键字确保当前方法线程在继续之前等待函数调用解决。

这就是为什么每个人都在日志flag set!之前打印。after

但是,您的执行被封装在.map. 这意味着,即使箭头函数本身被暂停,.map也不会。正如@zerkms 所提到的,它将您的数组变成了一系列承诺。

将其视为对远程 API 的实际异步调用。您不会等待服务器完成,所有来自 的调用.map都将完成,然后在它们返回时针对每个初始值进行评估。

这正是这里正在发生的事情。


推荐阅读