【问题标题】:Async function returning promise, instead of value异步函数返回承诺,而不是值
【发布时间】:2018-12-22 14:40:21
【问题描述】:

我试图了解 async/await 如何与 Promise 一起工作。

代码

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 应该是阻塞的,并且在上面的代码中,它似乎会阻塞返回带有原始 timestamp 的对象 bl。然后,我的函数返回原始值,但是时间变量设置为待处理的承诺而不是该原始值。我错过了什么?

【问题讨论】:

  • 这就是异步函数的作用——阅读spec
  • await should be blocking no - javascript 中的阻塞代码是一个“坏主意”™,async/await 与阻塞无关
  • Every async function 返回一个承诺,这样你就可以在其中 await 其他承诺,这就是重点
  • 这能回答你的问题吗? async/await implicitly returns promise?

标签: javascript promise async-await primitive


【解决方案1】:

异步前缀是 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 函数的翻译存在一些问题。用非常广泛的概念术语来说是可以的,但不能正确处理拒绝,有语法错误,并且给传递给承诺执行器的第二个参数(用于 拒绝承诺)... :-)
【解决方案2】:

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

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

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

const time = await latestTime();

例如,JavaScript 引擎正在获得对顶级 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 executor函数)被new Promise同步调用。
    • 这就是操作开始的原因,web3.eth.getBlock 被同步调用以开始工作。
  • 在 Promise 执行器中抛出的任何错误(等)都会被 new Promise 捕获并转换为 Promise 拒绝。
  • promise 回调中抛出的任何错误(等等)(例如我们传递的then)都将被捕获并转换为拒绝。

【讨论】:

    【解决方案3】:

    async 函数无论如何都会返回Promise。返回值将是`Promise,所以在你的情况下它将是:

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

    所以,你可以进一步使用它的功能:

    const time = await latestTime();
    

    但是为了获得关于async/await 功能的一般视图,最好阅读文档。

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多