异步函数返回承诺,而不是价值

Async function returning promise, instead of value

我正在尝试了解 async/await 如何与 promises 一起工作。

代码

async function latestTime() {
  const bl = await web3.eth.getBlock('latest');
  console.log(bl.timestamp); // Returns a primitive
  console.log(typeof bl.timestamp.then == 'function'); //Returns false - not a promise
  return bl.timestamp;
}
const time = latestTime(); // Promise { <pending> }

问题

据我所知,await 应该是阻塞的,在上面的代码中,它似乎阻塞了返回一个对象 bl 的原语 timestamp。然后,我的函数 returns 原始值,但是时间变量被设置为一个未决的承诺而不是那个原始值。我错过了什么?

异步前缀是 Promises 的一种包装器。

async function latestTime() {
    const bl = await web3.eth.getBlock('latest');
    console.log(bl.timestamp); // Returns a primitive
    console.log(typeof bl.timestamp.then == 'function'); //Returns false - not a promise
    return bl.timestamp;
}

相同
function latestTime() {
    return new Promise(function(resolve,success){
        const bl = web3.eth.getBlock('latest');
        bl.then(function(result){
            console.log(result.timestamp); // Returns a primitive
            console.log(typeof result.timestamp.then == 'function'); //Returns false - not a promise
            resolve(result.timestamp)
        })
}

async 函数将 return Promise 无论如何。 Return 值将是 `Promise,因此在您的情况下它将是:

async function latestTime(): Promise<some primitive> {
  const bl = await web3.eth.getBlock('latest');
  return bl.timestamp;
}

因此,您可以进一步使用它的功能,例如:

const time = await latestTime();

但是为了获得关于 async/await 功能的一般看法,阅读文档会更好。

一个async函数总是returns一个承诺。这就是它报告其异步工作完成的方式。如果你在另一个 async 函数中使用它,你可以使用 await 来等待它的 promise 结算,但在非 async 函数中(通常在顶层或在一个事件处理程序),你必须直接使用承诺,例如:

latestTime()
.then(time => {
    console.log(time);
})
.catch(error => {
    // Handle/report error
});

如果您在 JavaScript 模块的顶层执行此操作,某些环境现在支持即将推出的 top-level await in modules:

const time = await latestTime();
例如,

JavaScript 引擎正在支持 top-level awaitWebpack has experimental support for it


这里是您的 async 函数的粗略翻译,使用明确的 Promise 术语:

function latestTime() {
    return new Promise((resolve, reject) => {
        web3.eth.getBlock('latest')
        .then(bl => {
            console.log(bl.timestamp);
            console.log(typeof bl.timestamp.then == 'function');
            resolve(bl.timestamp);
        })
        .catch(reject);
    });
}

关于此的一些重要说明:

  • 您传递给 new Promise 的函数(promise 执行器 函数)被 new Promise 同步调用。
    • 这就是操作开始的原因,web3.eth.getBlock被同步调用以开始工作。
  • promise 执行器中抛出的任何错误(等)都会被 new Promise 捕获并转换为 promise 拒绝。
  • 在 promise 回调中抛出的任何错误(等)(比如我们传递的 then)都将被捕获并转换为拒绝。