如何在链中等待?

How to await in a chain?

这是 node.js 中的 Azure 函数 httpTrigger。如何等待 f1() 完成然后调用 f2()?

model.exports = main(param)  // async main plus await f1(param) don't wait either.
{
  f1(param)
  .then(
    good => f2(good, callback),  // execution jumps into f2 without waiting for f1 finishes
    bad => {...}
  );
}

async function f1(param)
{
  try
  {
    // await NOT wait here, 
    // but waits in Express
    await googlelib.verifyIdToken(something, (err, ok) =>
    {
      if (err) { return Promise.reject("Invalid"); }
      else     { return Promise.resolve("OK"); }
    });
  }
  catch (e) { return Promise.reject("catch"); }
}
      

如果 googlelib.verifyIdToken() 支持将 promises 作为其接口的内置部分(只要您不向其传递回调),那么您可以将代码更改为:

function f1(param) {
    return googlelib.verifyIdToken(something);
}

并且,您将直接 return googlelib.verifyIdToken() 提供的承诺,允许调用者在 [=16] 的结果上使用 await.then() =] returns.


如果 googlelib.verifyIdToken() 不支持将 promises 作为其接口的内置部分(当您不向其传递回调时),那么您可以自己“promisify”它:

const {promisify} = require('util');

// create promisified interface .verifyIdTokenP
googlelib.verifyIdTokenP = promisify(googlelib.verifyIdToken);

// use that promisified interface
function f1(param) {
    return googlelib.verifyIdTokenP(something);
}

这个手动 promise 函数的过程适用于任何支持“nodejs 异步调用约定”的异步 API,其中函数接受回调作为最后一个参数,并且回调将使用两个参数作为callback(err, value)。如果异步 API 的工作方式与此不同,那么您不能为它使用 util.promisify() 函数,而必须手动将其包装在您自己的 promise 中。