如何避免缩进嵌套承诺?

How to avoid indented nested promises?

我听说 promise 在代码中应该是线性的,而不是回调(“回调地狱”)。

虽然我还有一个类似于回调地狱的场景,希望promise能够实现他们的promise,并且有一个等价于这个问题代码的线性语法。

给定承诺 p()q()w() 考虑此代码:

p().then(() => {
    q().then(() => {
       w().then(() => {
           // do something
       })
    })
})

我们能否为每个嵌套的 promise 制作一个不缩进的等效代码?

您可以尝试使用 async/await,这样可以留下更简洁的代码。应该是这样的:

(async () => {
    try {
        await p();
        await q();
        await w();
    } catch (e) {
        // handle error
    }
})()

如果每个承诺之间没有依赖关系,您可以使用 await Promise.all 来“全有或全无”。在任何其他情况下,您可以存储返回值并将其传递给下一个函数,以便在需要时使用。

正如另一位用户提到的,您可以使用 async/await,但另一种选择只是稍微重组您拥有的内容。以下是一些可行的示例——取决于您何时何地需要某些数据:

p()
  .then(q)
  .then(w)

// OR

p()
  .then(() => q())
  .then(() => w())

显然,如果 w() 需要来自 p()q() 的数据,这会变得有点复杂,但这就是它的要点。

您不应嵌套 .then() 处理程序,而应让每个 .then() 创建并 return 一个新的 Promise。这就是它设计的工作方式,否则你仍然处于回调地狱,现在是带有承诺的版本。差别不大。

代码应该是这样的:

p()
  .then(() => {
    return q();
  })
  .then(() => {
    return w();
  })
  .then(() => {
    // do something
  });

如果 .then() 处理程序所做的只是调用下一个函数,您可以将其编写为更简单的形式(阅读 arrow functions):

p()
  .then(() => q())
  .then(() => w())
  .then(() => {
    // do something
  });

更进一步,如果不带参数调用qw,代码可以像这样简单:

p()
  .then(q)
  .then(w)
  .then(() => {
    // do something
  });

或者您可以更进一步,而不是使用 .then() and .catch() you use await。代码变得更加清晰易读:

try {
  await p();
  await q();
  await w();
  // do something
} catch (err) {
  // write here the code you would write in the handler you pass to `.catch()
  // in the approach that uses Promises
}

备注

如果上面使用 await 的代码在函数中使用,则该函数必须是 async function(只需将 async 放在其定义前面)。

使用 await may or may not be used outside of a function 的代码(即在模块的顶层)取决于 运行 您使用 运行 它的时间(浏览器,Node.js等)。