我的代码是:
async function run() {
await sleep(1);
fs.readFile('list.txt', 'utf8', function (err, text) {
console.log(text);
await sleep(5);
});
}
run();
await sleep(1)
很好,但是await sleep(5)
会导致:
SyntaxError:异步仅在异步函数中有效
fs.readFile
是问题吗?在这种情况下如何使用await
?
上面是测试的简化示例。在我的实际用法中,我需要将await sleep
放在深度嵌套在更多异步函数中的回调中。
答案 0 :(得分:4)
我不确定sleep
在做什么,但是您问题中的问题正在发生,因为对fs.readfile
的回调不是异步函数,而await sleep(5)
在哪里
async function run() {
await sleep(1);
fs.readFile('list.txt', 'utf8', function (err, text) {
console.log(text); /* ^this isn't an async function */
await sleep(5);
});
}
您可以通过将异步函数作为回调传递来消除该错误,但是不建议将promise和回调流混合使用,这会导致问题,尤其是在处理错误时。这样可以防止您链接诺言并从run()
外部的内部等待中捕获错误。
一种更好的方法是将fs.readFile()
包装在一个诺言中,然后等待。
async function run() {
await sleep(1);
const text = await new Promise((resolve, reject) => {
fs.readFile('list.txt', 'utf8', function (err, text) {
if (err) reject(err) else resolve(text);
});
});
console.log(text);
await sleep(5);
}
这将使您可以使用以下更强大的方式捕获任何错误:
run()
.then(() => /*...*/)
.catch(err => /* handle error */
并避免未处理的拒绝。
答案 1 :(得分:4)
上面是测试的简化示例。在我的实际用法中,我需要将await睡眠置于深度嵌套在更多异步函数中的回调中。
在有机会遵守承诺的情况下,不应使用async..await
来增强基于回调的API或一般而言的承诺(如果多次调用回调可能无法实现)。这会导致不良的控制流程和错误处理。
一旦async
中有run
个回调函数,就不可能将嵌套的promise与run().then(...)
链接起来。嵌套承诺中的错误也可能无法处理,并导致UnhandledPromiseRejectionWarning
。
正确的方法是从回调转移到Promise,并使用Promise控制流。通常,这可以通过promise构造函数来实现:
async function run() {
await sleep(1);
const text = await new Promise((resolve, reject) => {
fs.readFile('list.txt', 'utf8', function (err, text) {
if (err) reject(err) else resolve(text);
});
});
console.log(text);
await sleep(5);
}
有numerous ways可以从基于Node回调的API获得承诺,例如fs
从节点10开始提供Promise API:
async function run() {
await sleep(1);
const text = await fs.promises.readFile('list.txt', 'utf8');
console.log(text);
await sleep(5);
}
答案 2 :(得分:0)
在功能启动之前,您必须使用 aysnc 键。 等待关键字 无法使用正常功能。
async function run() {
await sleep(1);
fs.readFile('list.txt', 'utf8', async function (err, text) {
console.log(text);
await sleep(5);
});
}
run();
答案 3 :(得分:0)
如果函数包含“ await”,则必须必须在函数声明中添加“ async”前缀。
注意:通过将函数设为“异步”函数,将始终返回承诺。因此,如果您返回一个字符串,则该字符串将自动包装在Promise对象中。
因此,您可以手动返回Promise(为清晰起见)。一个简单的解决承诺就足够了:
async function foo(){
await bar();
return Promise.resolve('optional'); // optionally resolve with a value
}
关键字“异步”始终位于关键字“功能”之前:
var foo = async function(){
await bar();
return Promise.resolve('optional'); // optionally resolve with a value
}
...以及箭头功能很好:
var foo = sally( async () => {
await bar();
return Promise.resolve('optional'); // optionally resolve with a value
})
要获取返回值:
foo().then(val => console.log(val) ); // prints "optional" to console