我已经阅读了async/await,在阅读了几篇文章之后,我决定自己测试一下。然而,我似乎不明白为什么这行不通:

async function main() {  
    var value = await Promise.resolve('Hey there');
    console.log('inside: ' + value);
    return value;
}

var text = main();  
console.log('outside: ' + text);

控制台输出以下内容(节点v8.6.0):

> outside: [object Promise] > inside:嘿,大家好

为什么函数内部的日志消息之后执行?我认为创建async/await的原因是为了使用异步任务执行同步执行。

是否有一种方法可以使用函数内部返回的值,而不使用main()后的.then() ?


当前回答

我喜欢这种聪明的语法来从入口点执行异步工作

void async function main() {
  await doSomeWork()
  await doMoreWork()
}()

其他回答

这个问题的实际解决方案是采用不同的方法。

可能您的目标是某种初始化,这通常发生在应用程序的顶层。

解决方案是确保在应用程序的顶层只有一个JavaScript语句。如果你在应用程序的顶部只有一条语句,那么你可以在任何地方的其他任何地方自由地使用async/await(当然要遵守正常的语法规则)。

换句话说,把你的整个顶层包装在一个函数中,这样它就不再是顶层了,这就解决了如何在应用程序的顶层运行async/await的问题——你不需要。

这是你的应用程序的顶层应该是这样的:

import {application} from './server'

application();

现在使用ECMAScript22,我们可以在顶级模块中使用await。

这是一个使用(await顶层)的例子:

const response = await fetch("...");
console.log(response):

另一个没有(await顶层)的示例

  async function callApi() {
    const response = await fetch("...");
    console.log(response)      
}
callApi()

现在可以在Node v13.3.0中使用顶级await

import axios from "axios";

const { data } = await axios.get("https://api.namefake.com/");
console.log(data);

使用——harmony-top-level-await标志运行它

节点——harmony-top-level-await index.js

在当前答案的基础上提供一些进一步的信息:

node.js文件的内容目前以类似字符串的方式连接起来,以形成一个函数体。

例如,如果你有一个文件test.js:

// Amazing test file!
console.log('Test!');

然后node.js会秘密地连接一个函数,看起来像这样:

function(require, __dirname, ... perhaps more top-level properties) {
  // Amazing test file!
  console.log('Test!');
}

需要注意的主要事情是,得到的函数不是一个异步函数。所以你不能在里面直接使用await这个词!

但是如果你需要使用这个文件中的承诺,那么有两种可能的方法:

不要在函数中直接使用await 完全不要使用await

选项1要求我们创建一个新的作用域(这个作用域可以是异步的,因为我们可以控制它):

// Amazing test file!
// Create a new async function (a new scope) and immediately call it!
(async () => {
  await new Promise(...);
  console.log('Test!');
})();

选项2要求我们使用面向对象的承诺API(使用承诺的不太漂亮但功能相同的范例)

// Amazing test file!
// Create some sort of promise...
let myPromise = new Promise(...);

// Now use the object-oriented API
myPromise.then(() => console.log('Test!'));

看到节点添加对顶级await的支持会很有趣!

我喜欢这种聪明的语法来从入口点执行异步工作

void async function main() {
  await doSomeWork()
  await doMoreWork()
}()