我已经阅读了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() ?


当前回答

现在可以在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

其他回答

节点, 你可以在REPL中运行node——experimental-repl-await。我不太确定脚本。

Deno - Deno已经内置了它。

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

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

顶级等待已经转移到阶段3阶段4(见namo的评论),所以你的问题的答案是我如何在顶级使用async/await ?就是使用await:

const text = await Promise.resolve('Hey there');
console.log('outside: ' + text)

如果你想要main()函数:在main()调用中添加await:

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

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

兼容性

v8自2019年10月起 Chrome DevTools, Node.js和Safari web检查器中的REPL 标志后面的节点v13.3+——harmony-top-level-await TypeScript 3.8+(发行) Deno自2019年10月起 Webpack@v5.0.0-alpha.15

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

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的支持会很有趣!

在NodeJS 14.8+中,你可以使用顶级的await模块(#3解决方案)。你也可以将.js重命名为.mjs (ES模块)而不是.js(。cj CommonJS)。