简体   繁体   English

如何在JavaScript中的异步Promise中使用同步?

[英]How to use sync within an async Promise in JavaScript?

When I run the following code: 当我运行以下代码时:

b = async attempt => {
  if (attempt == 5) {
    return;
  }
  console.log("Starting attempt:", attempt);
  b(attempt + 1).then(() => {
    console.log("Finished attempt:", attempt);
  });
};
b(0);

The output is: 输出是:

Starting attempt: 0
Starting attempt: 1
Starting attempt: 2
Starting attempt: 3
Starting attempt: 4
Finished attempt: 4
Finished attempt: 3
Finished attempt: 2
Finished attempt: 1
Finished attempt: 0

However, I want to call another promise a before each recursive call as follows: 但是,我想在每次递归调用之前调用另一个promise a ,如下所示:

a = Promise.resolve();
b = async attempt => {
  if (attempt == 5) {
    return;
  }
  console.log("Starting attempt:", attempt);
  a.then(() => {
    b(attempt + 1);
  }).then(() => {
    console.log("Finished attempt:", attempt);
  });
};
b(0);

Now the output is: 现在的输出是:

Starting attempt: 0
Starting attempt: 1
Starting attempt: 2
Finished attempt: 0
Starting attempt: 3
Finished attempt: 1
Starting attempt: 4
Finished attempt: 2
Finished attempt: 3
Finished attempt: 4

How can I modify the second code block to ensure that the output is the same as the first code block? 如何修改第二个代码块以确保输出与第一个代码块相同?

If I understand your question correctly, then the issue is cause by nested promises and calls to asynchronous functions (ie b(attempt + 1) ) not blocking execution of the enclosing function. 如果我正确理解你的问题,那么问题是由嵌套的promises和对异步函数的调用(即b(attempt + 1) )而不是阻止执行封闭函数。 This in turn produces unordered, and unexpected logging results. 这反过来会产生无序和意外的记录结果。

Consider revising the call to b() , by return the promise of b(attempt + 1); 考虑修改对b()的调用, return b(attempt + 1);的承诺b(attempt + 1); to ensure that the following log: console.log("Finished attempt:", attempt) is executed after completion of b() completes: 确保在完成b()完成后执行以下日志: console.log("Finished attempt:", attempt)

 const a = Promise.resolve(); const b = async attempt => { if (attempt == 5) { return; } console.log("Starting attempt:", attempt); await a.then(() => { /* Return the project of b() here, has similar effect to that of await keyword */ return b(attempt + 1); }).then(() => { console.log("Finished attempt:", attempt); }); }; b(0); 

You are breaking the promise chain by not returning an inner promise a.then(() => {b(attempt + 1);}) . 你是通过不返回内部承诺来打破承诺链a.then(() => {b(attempt + 1);}) Adding return statement should help. 添加return语句应该有所帮助。

Also I would recommend not to mix async/await syntax with .then and callbacks. 另外我建议不要将async/await语法与.then和callbacks混合使用。

The following code looks more "synchronous" and does the trick. 以下代码看起来更“同步”并且可以解决问题。

 const a = Promise.resolve(); const b = async attempt => { if (attempt == 5) { return; } console.log("Starting attempt:", attempt); await a await b(attempt + 1) console.log(`Finished attempt: ${attempt}`) }; b(0); 

You forgot to return the promise chains that you are creating: 您忘记return您正在创建的承诺链:

const b = attempt => {
  if (attempt == 5) {
    return Promise.resolve();
  }
  console.log("Starting attempt:", attempt);
  const a = Promise.resolve();
  return a.then(() => {
//^^^^^^
    return b(attempt + 1);
//  ^^^^^^
  }).then(() => {
    console.log("Finished attempt:", attempt);
  });
};
b(0).then(() => {
  console.log("done");
});

Only with those return s, the caller of the function will be able to wait for the promise. 只有那些return s,函数的调用者才能等待承诺。 Your first snippet has the same issue. 您的第一个代码段也有同样的问题。 It would've been more obvious if you had omitted the async keyword, so that it was clear that b() didn't return a promise. 如果你省略了async关键字会更加明显,因此很明显b()没有返回一个promise。

If you want to use async / await , your code should look like this: 如果要使用async / await ,则代码应如下所示:

const b = async attempt => {
  if (attempt == 5) {
    return;
  }
  console.log("Starting attempt:", attempt);
  await Promise.resolve();
//^^^^^
  await b(attempt + 1);
//^^^^^
  console.log("Finished attempt:", attempt);
};
b(0).then(() => {
  console.log("done");
});

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

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