简体   繁体   English

如何在JavaScript中迭代多个异步等待函数并链接在一起?

[英]How to iterate multiple async await functions and chain together in JavaScript?

I'm new in JavaScript and Node.js. 我是JavaScript和Node.js的新手。 I have the following code: 我有以下代码:

  const populateSetup = async () => {
  token = await getToken();

  const promises = await constant.accounts.map(async (x) => {
    const accountId = await createAccountRequest(x.account);
    const peoid = await createPeopleRequests(x.people);
    const pid = await createProjectsRequests(x.project);

    return [accountId, pid, peoid];
  });

  const [accountId, pid, peoid] = await Promise.all(promises);
};

In the above, token is first fetched and is required to create account and then accountId returned is required to create people and projects. 在上面的代码中,首先获取令牌并创建帐户需要令牌,然后需要返回的accountId来创建人员和项目。 Let's say I have the following input: 假设我输入以下内容:

    exports.accounts = [
  { account: this.testAccountFirst, project: this.projectOne, people: this.testUserOne },
  { account: this.testAccountSecond, project: this.projectTwo, people: this.testUserTwo },
];

After running the populateSetup() in node environment my result is (not the console output but the output of the populateSetup() : 在节点环境中运行populateSetup() ,我的结果是(不是控制台输出,而是populateSetup()的输出:

testAccountFirst has 1 people -> testUserOne
testAccountSecond has 2 projects and 1 user -> projectOne, projectTwo, testUserTwo

expected result is: 预期结果是:

testAccountFirst should have 1 project and 1 people -> projectOne, testUserOne
testAccountSecond should have 1 project and 1 people -> projectTwo, testUserTwo

The problem here is that the accountId of first account is not sent to the projectsRequest. 这里的问题是第一个帐户的accountId没有发送到projectsRequest。 I don't know how to resolve this. 我不知道该如何解决。 I have gone through this Stackoverflow question but still couldn't figure out. 我已经解决了这个Stackoverflow问题,但仍然无法弄清楚。

I'm having a hard time understanding exactly what question you're asking, but .map() is not async savvy. 我很难理解您要问的是什么问题,但是.map()并不精通异步。 That means that even though you declare the callback as async , .map() doesn't do anything with the promise that returns and thus it doesn't wait to start the 2nd iteration before the 1st iteration is done. 这意味着即使您将回调声明为async.map()也不会对返回的承诺做任何事情,因此,它不会等到第一次迭代完成后才开始第二次迭代。 Therefore, you end up running all the async operations from all the iterations of the loop in parallel and they can finish in any random order. 因此,最终您将并行运行循环的所有迭代中的所有异步操作,并且它们可以以任何随机顺序完成。

If you really want to run them sequentially, one after another, then switch your .map() to a for loop because a for loop will wait for an await in the first iteration of the loop before starting the 2nd iteration of the loop and so on... 如果您真的想依次运行它们,则将.map()切换到for循环,因为for循环将在循环的第一次迭代中await ,然后再开始循环的第二次迭代,因此上...

return [accountId, pid, peoid]; is returning resolved promises, also, you wait one promise resolving after another. 还返回已解决的承诺,您也要等一个承诺再解决。 For example, if one resolving is 5 sec, then you need to wait 5+5+5=15 secs 例如,如果一个解析时间是5秒,那么您需要等待5 + 5 + 5 = 15秒

But more of that, it is bad practice to use .map() with promises inside, because it is sync operator. 但是更多的是,在内部使用带有保证的.map()是不好的做法,因为它是同步运算符。 In your case, I would use something like that: 在您的情况下,我将使用类似的方法:

const populateSetup = async () => {
  const token = await getToken();

  const [accountId, peoid, pid] =[
    createAccountRequest(x.account),
    createPeopleRequests(x.people),
    createProjectsRequests(x.project)
  ]

  return Promise.all([accountId, peoid,pid])
};

Here, You return promise, that can be used like this: 在这里,您返回promise,可以像这样使用:

const [accountId, peoid,pid] = await populateSetup()

Promise.all() do promise execution simultaniosly and wait for all to be resolved, so it is 5 secs instead of 15 Promise.all()确实同时承诺执行并等待所有问题解决,所以它是5秒而不是15秒

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM