我一直在浏览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):
>外:[对象承诺]
>里面:嘿那里
为什么函数内部的日志消息会在之后执行?我认为创建async / await的原因是为了使用异步任务执行同步执行。
有没有办法在.then()
后使用main()
之后使用函数内返回的值?
答案 0 :(得分:103)
我似乎无法理解为什么这不起作用。
因为Personid Forename Surname Groupid count
1 John Bloggs 1 2
2 Josh Bloggs 1 2
3 Bert Bloggs 1 2
4 Owen Jones 2 1
5 Jack Rose 3 1
返回一个承诺;所有main
函数都可以。
在顶级,您必须:
使用永不拒绝的顶级async
函数,或
使用async
和then
catch
函数async
注意(async () => {
try {
var text = await main();
console.log(text);
} catch (e) {
// Deal with the fact the chain failed
}
})();
;你必须处理承诺拒绝/异步异常,因为没有别的东西;你没有调用者将它们传递给。如果您愿意,可以通过catch
函数(而不是catch
/ try
语法)调用它的结果:
catch
......这更简洁一些(因为这个原因,我喜欢它)。
(async () => {
var text = await main();
console.log(text);
})().catch(e => {
// Deal with the fact the chain failed
});
和then
catch
如果链中或main()
.then(text => {
console.log(text);
})
.catch(err => {
// Deal with the fact the chain failed
});
处理程序中发生错误,将调用catch
处理程序。 (确保您的then
处理程序不会抛出错误,因为没有注册任何错误来处理它们。)
或catch
的两个参数:
then
再次注意我们正在注册拒绝处理程序。但是在这种形式中,请确保您的main().then(
text => {
console.log(text);
},
err => {
// Deal with the fact the chain failed
}
);
回调都没有抛出任何错误,没有注册任何错误来处理它们。
答案 1 :(得分:4)
您现在可以在Node v14.3.0
中使用顶级等待import axios from "axios";
const { data } = await axios.get("https://api.namefake.com/");
console.log(data);
使用--harmony-top-level-await
标志运行它
node --harmony-top-level-await index.js
答案 2 :(得分:2)
解决此问题的实际方法是采用不同的方法。
您的目标可能是某种初始化,通常发生在应用程序的顶层。
解决方案是确保应用程序的顶层只有一个JavaScript语句。如果您的应用程序顶部只有一条语句,那么您可以在其他任何地方随意使用async / await(当然,这取决于常规语法规则)
采用另一种方法,将整个顶层包装在一个函数中,以使其不再是顶层,从而解决了如何在应用程序的顶层运行异步/等待的问题-您无需这样做。 / p>
这是应用程序顶层的外观:
import {application} from './server'
application();
答案 3 :(得分:1)
要在当前答案的基础上提供更多信息:
node.js
文件的内容目前以类似字符串的方式串联在一起,以形成函数主体。
例如,如果您有文件test.js
:
// Amazing test file!
console.log('Test!');
然后node.js
将秘密连接一个看起来像这样的函数:
function(require, __dirname, ... a bunch more top-level properties) {
// Amazing test file!
console.log('test!');
}
要注意的主要事情是,结果函数不是异步函数。因此,您不能在其内部直接使用术语await
!
但是说您需要在此文件中使用Promise,那么有两种可能的方法:
await
await
选项1要求我们创建一个新的作用域(该作用域可以为async
,因为我们可以控制它):
// Amazing test file!
// Create a new async function (a new scope) and immediately call it!
(async () => {
await new Promise(...);
console.log('Test!');
})();
选项2要求我们使用面向对象的Promise API(使用Promise的方式不太漂亮,但功能相同)
// Amazing test file!
// Create some sort of promise...
let myPromise = new Promise(...);
// Now use the object-oriented API
myPromise.then(() => console.log('Test!'));
我个人希望,如果可行,默认情况下,node.js将代码连接到async
函数中。这样可以摆脱这种头痛。
答案 4 :(得分:1)
Top-Level await
已进入阶段3,因此您的问题我如何才能在顶层使用async / await?的答案是只添加await
个呼叫到main()
:
async function main() {
var value = await Promise.resolve('Hey there');
console.log('inside: ' + value);
return value;
}
var text = await main();
console.log('outside: ' + text)
或者只是:
const text = await Promise.resolve('Hey there');
console.log('outside: ' + text)
请记住,它仍然仅在Webpack@v5.0.0-alpha.15中可用。
答案 5 :(得分:1)
节点-
您可以在REPL中运行node --experimental-repl-await
。我对脚本不太确定。
Deno -
Deno已经内置了它。
答案 6 :(得分:1)
我喜欢这种巧妙的语法从入口点执行异步工作
void async function main() {
await doSomeWork()
await doMoreWork()
}()
答案 7 :(得分:0)
由于main()
以异步方式运行,因此返回一个promise。您必须使用then()
方法获得结果。由于then()
也会返回承诺,因此您必须致电process.exit()
以结束该计划。
main()
.then(
(text) => { console.log('outside: ' + text) },
(err) => { console.log(err) }
)
.then(() => { process.exit() } )
答案 8 :(得分:0)
顶级等待是即将到来的EcmaScript标准的一项功能。目前,您可以在TypeScript 3.8(目前为RC版本)中开始使用它。
您可以使用以下命令开始使用TypeScript 3.8 by installing it from npm:
$ npm install typescript@rc
这时,您需要添加rc
标签以安装最新的Typescript 3.8版本。
答案 9 :(得分:0)
其他解决方案缺乏 POSIX 合规性的一些重要细节:
你需要...
stderr
输出流发出错误。#!/usr/bin/env node
async function main() {
// ... await stuff ...
}
// POSIX compliant apps should report an exit status
main()
.then(() => {
process.exit(0);
})
.catch(err => {
console.error(err); // Writes to stderr
process.exit(1);
});
如果您使用像 commander 这样的命令行解析器,您可能不需要 main()
。
示例:
#!/usr/bin/env node
import commander from 'commander'
const program = new commander.Command();
program
.version("0.0.1")
.command("some-cmd")
.arguments("<my-arg1>")
.action(async (arg1: string) => {
// run some async action
});
program.parseAsync(process.argv)
.then(() => {
process.exit(0)
})
.catch(err => {
console.error(err.message || err);
if (err.stack) console.error(err.stack);
process.exit(1);
});
答案 10 :(得分:0)
在 NodeJS 14.8+ 中,您可以使用顶级 await 模块(#3 解决方案)。您也可以将 .js 重命名为 .mjs(ES 模块)而不是 .js(.cjs CommonJS)。