Fel*_*ipe 117 javascript node.js async-await ecmascript-2017
我一直在浏览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);
Run Code Online (Sandbox Code Playgroud)
控制台输出以下内容(节点v8.6.0):
>外面:[对象承诺]
>里面:嘿那里
为什么函数内部的日志消息会在之后执行?我认为创建async/await的原因是为了使用异步任务执行同步执行.
有没有办法可以使用函数内部返回的值而不使用asyncafter await?
T.J*_*der 167
我似乎无法理解为什么这不起作用.
因为main回报承诺; 所有async功能都有.
在顶层,您必须:
使用async永不拒绝的顶级函数,或
使用then和catch
await永不拒绝的顶级功能(async () => {
try {
var text = await main();
console.log(text);
} catch (e) {
// Deal with the fact the chain failed
}
})();
Run Code Online (Sandbox Code Playgroud)
注意await; 你必须处理承诺拒绝/异步异常,因为没有别的东西; 你没有调用者将它们传递给.如果您愿意,可以通过async函数(而不是catch/ catchsyntax)调用它的结果:
(async () => {
var text = await main();
console.log(text);
})().catch(e => {
// Deal with the fact the chain failed
});
Run Code Online (Sandbox Code Playgroud)
...这更简洁一些(因为这个原因,我喜欢它).
try和catchmain()
.then(text => {
console.log(text);
})
.catch(err => {
// Deal with the fact the chain failed
});
Run Code Online (Sandbox Code Playgroud)
then如果链中或catch处理程序中发生错误,将调用该处理程序.(确保您的catch处理程序不会抛出错误,因为没有注册任何错误来处理它们.)
或两个论点then:
main().then(
text => {
console.log(text);
},
err => {
// Deal with the fact the chain failed
}
);
Run Code Online (Sandbox Code Playgroud)
再次注意我们正在注册一个拒绝处理程序.但在这种形式中,请确保您的catch回调都没有抛出任何错误,没有注册任何错误来处理它们.
lau*_*gan 23
顶级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)
Run Code Online (Sandbox Code Playgroud)
要不就:
const text = await Promise.resolve('Hey there');
console.log('outside: ' + text)
Run Code Online (Sandbox Code Playgroud)
--harmony-top-level-awaitGer*_*ica 10
要在当前答案之上提供更多信息:
node.js文件的内容当前以类似字符串的方式连接起来,形成一个函数体。
例如,如果您有一个文件test.js:
// Amazing test file!
console.log('Test!');
Run Code Online (Sandbox Code Playgroud)
然后node.js将秘密连接一个如下所示的函数:
function(require, __dirname, ... perhaps more top-level properties) {
// Amazing test file!
console.log('Test!');
}
Run Code Online (Sandbox Code Playgroud)
需要注意的主要事情是生成的函数不是异步函数。所以你不能await直接在它里面使用这个词!
但是如果你需要在这个文件中使用 promises,那么有两种可能的方法:
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!');
})();
Run Code Online (Sandbox Code Playgroud)
选项 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!'));
Run Code Online (Sandbox Code Playgroud)
看到节点添加对顶级的支持会很有趣await!
您现在可以在Node v13.3.0 中使用顶级 await
import axios from "axios";
const { data } = await axios.get("https://api.namefake.com/");
console.log(data);
Run Code Online (Sandbox Code Playgroud)
用--harmony-top-level-await标志运行它
node --harmony-top-level-await index.js
其他解决方案缺乏 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);
});
Run Code Online (Sandbox Code Playgroud)
如果您使用像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);
});
Run Code Online (Sandbox Code Playgroud)
这个问题的实际解决方案是以不同的方式处理它。
可能您的目标是某种初始化,通常发生在应用程序的顶层。
解决方案是确保在您的应用程序的顶层只有一个 JavaScript 语句。如果您的应用程序顶部只有一个语句,那么您可以在任何其他地方随意使用 async/await(当然要遵守正常的语法规则)
换句话说,将整个顶层包装在一个函数中,使其不再是顶层,这解决了如何在应用程序的顶层运行 async/await 的问题 - 你没有。
这是您的应用程序的顶层应该是这样的:
import {application} from './server'
application();
Run Code Online (Sandbox Code Playgroud)
我喜欢这种巧妙的语法从入口点执行异步工作
void async function main() {
await doSomeWork()
await doMoreWork()
}()
Run Code Online (Sandbox Code Playgroud)
上面的大多数答案都有些过时或非常冗长,所以这里有一个节点 14 以后的快速示例。
制作一个名为 的文件runme.mjs:
import * as util from "util";
import { exec as lameExec } from "child_process";
const exec = util.promisify(lameExec);
const log = console.log.bind(console);
// Top level await works now
const { stdout, stderr } = await exec("ls -la");
log("Output:\n", stdout);
log("\n\nErrors:\n", stderr);
Run Code Online (Sandbox Code Playgroud)
跑 node runme.mjs
Output:
total 20
drwxr-xr-x 2 mike mike 4096 Aug 12 12:05 .
drwxr-xr-x 30 mike mike 4096 Aug 12 11:05 ..
-rw-r--r-- 1 mike mike 130 Aug 12 12:01 file.json
-rw-r--r-- 1 mike mike 770 Aug 12 12:12 runme.mjs
Errors:
Run Code Online (Sandbox Code Playgroud)
对于浏览器,您需要添加type="module"
没有type="module"
<script>
const resp = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await resp.json();
console.log(users)
</script>Run Code Online (Sandbox Code Playgroud)
和type="module"
<!--script type="module" src="await.js" -->
<script type="module">
const resp = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await resp.json();
console.log(users)
</script>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
42400 次 |
| 最近记录: |