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

Posted

技术标签:

【中文标题】异步函数返回承诺,而不是值【英文标题】: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? 【参考方案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 引擎正在获得对*** await 和 Webpack 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 功能的一般视图,最好阅读文档。

【讨论】:

以上是关于异步函数返回承诺,而不是值的主要内容,如果未能解决你的问题,请参考以下文章

Javascript - 异步等待和获取 - 返回值,而不是承诺?

获取静态函数以返回异步值

承诺等待得到解决而不返回

为啥我的异步函数返回 Promise <pending> 而不是一个值?

React Native AsyncStorage getItem 返回承诺而不是值

从异步函数返回值