lib/helper.js
中写了这段代码var myfunction = async function(x,y) {
....
return [variableA, variableB]
}
exports.myfunction = myfunction;
,然后尝试在另一个文件中使用它
var helper = require('./helper.js');
var start = function(a,b){
....
const result = await helper.myfunction('test','test');
}
exports.start = start;
我遇到了错误
”在异步函数中有效”
问题是什么?
#1 楼
该错误不是引用myfunction
,而是引用start
。async function start() {
....
const result = await helper.myfunction('test', 'test');
}
// My function
const myfunction = async function(x, y) {
return [
x,
y,
];
}
// Start function
const start = async function(a, b) {
const result = await myfunction('test', 'test');
console.log(result);
}
// Call start
start();
我利用这个问题的机会向您建议使用
await
的已知反模式,即:return await
。错误
async function myfunction() {
console.log('Inside of myfunction');
}
// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later
// useless async here
async function start() {
// useless await here
return await myfunction();
}
// Call start
(async() => {
console.log('before start');
await start();
console.log('after start');
})();
校正
async function myfunction() {
console.log('Inside of myfunction');
}
// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later
// Also point that we don't use async keyword on the function because
// we can simply returns the promise returned by myfunction
function start() {
return myfunction();
}
// Call start
(async() => {
console.log('before start');
await start();
console.log('after start');
})();
此外,还要知道
return await
是正确且重要的特殊情况:(使用try / catch)是否存在性能问题与“返回等待”?
评论
但这不起作用,我更新了代码。我仍然遇到相同的错误
– j.doe
18年3月22日在15:35
@ j.doe我添加了一个片段
–‐Orelsanpls
18年3月22日在15:53
谢谢,我发现了我的问题。我试图在回调函数start()函数中执行此操作。解决方法是:const start = async function(a,b){task.get(options,async function(error,result1){const result = await myfunction('test','test');
– j.doe
18年3月22日在16:00
考虑到Node是单线程的。这样做不是每分钟减少请求,也增加了两次填充请求之间的延迟。
–瑞沙卜·迪曼(Rishabh Dhiman)
19年9月8日在15:40
值得一提的是,在“ CORRECT”示例中,没有必要将start声明为异步函数(尽管为了明确起见,有些人还是会选择这样做)
– Gershom
1月7日20:02
#2 楼
当我收到此错误时,事实证明我在“异步”函数中调用了map函数,因此此错误消息实际上是指未标记为“异步”的map函数。通过从map函数中取消“ await”调用并提出了一些其他方法来获得预期的行为,我解决了这个问题。var myfunction = async function(x,y) {
....
someArray.map(someVariable => { // <- This was the function giving the error
return await someFunction(someVariable);
});
}
评论
这是我的问题。我用for循环替换了map函数,这对我来说是一个简单的解决方案。但是,此解决方案可能不适用于您,具体取决于您的代码。
–托马斯
19年3月13日在20:26
仅供参考,您也可以执行someArray.map(async(someVariable)=> {return await someFunction(someVariable)})
– ptim
19年4月10日在13:02
代码中的等待会产生误导,因为Array.map不会将函数作为异步函数进行处理。完全清楚,在map函数完成之后,someFunction将全部处于挂起状态。如果要真正等待函数完成,则必须编写:a。等待Promise.all(someArray.map(someVariable => someFunction(someVariable)))或a。等待Promise.all(someArray.map(someFunction)))。
–‐Orelsanpls
1月8日17:04
#3 楼
要使用await
,其执行上下文本质上必须是async
如前所述,您需要定义
executing context
的性质,在此之前您要先执行await
一个任务。 只需将
async
放在将执行fn
任务的async
声明之前。var start = async function(a, b) {
// Your async task will execute with await
await foo()
console.log('I will execute after foo get either resolved/rejected')
}
说明:
在您的问题中,您要导入一个本质上为
method
的asynchronous
,它将并行执行。但是,在您尝试执行async
方法的地方是另一个execution context
,您需要定义async
才能使用await
。 var helper = require('./helper.js');
var start = async function(a,b){
....
const result = await helper.myfunction('test','test');
}
exports.start = start;
想知道引擎盖下发生了什么
/>
await
使用promise / future /返回任务的方法/功能,而async
将方法/功能标记为能够使用await。 另外,如果您熟悉
promises
,则await
实际上会执行相同的promise / resolve过程。创建承诺链并在resolve
回调中执行下一个任务。有关更多信息,请参考MDN DOCS。
评论
即使在启动功能中出现异步,我仍然收到错误
– j.doe
18年3月22日在15:49
我不确定您在哪里丢失此错误,没有解决此类错误的复杂解释。
–萨蒂扬·帕塔克(Satyam Pathak)
18 Mar 22 '18 at 15:58
这是一个正确的答案,并且实际上解释了下划线的原因。投票。
– linehrr
19-10-10在19:54
#4 楼
async
/ await
的当前实现仅支持await
函数内部的async
关键字更改start
函数签名,以便可以在await
内部使用start
。 var start = async function(a, b) {
}
对于感兴趣的人,顶级
await
的提案目前处于第2阶段:https://github.com/tc39/proposal-top-level-等待评论
不幸的是,这基本上意味着您将必须在整个代码库中使所有函数异步。因为如果要使用await,则必须在异步函数中执行此操作,这意味着您必须在调用该函数的函数中等待该函数的响应-再次,这意味着您所有的函数都需要变为异步状态。对我而言,这意味着尚未准备好使用await异步。当您可以使用await调用异步方法时,无论当前函数是同步还是异步,那么它将准备好进行黄金时段。
–罗德尼·巴尔巴蒂(Rodney P. Barbati)
1月7日19:16
依赖于外部过程结果的,通过任何间接级别的每个函数都必须并且应该使用异步定义-这就是异步的全部要点。
– Gershom
1月7日20:16
您当前可以使用--experimental-repl-await选项在节点repl中使用它。
– Artagna
5月21日12:00
#5 楼
我遇到了同样的问题,以下代码块给出了相同的错误消息:repositories.forEach( repo => {
const commits = await getCommits(repo);
displayCommit(commits);
});
问题是方法getCommits()是异步的,但我正在传递它也是由Promise产生的参数回购。因此,我必须像这样向其添加async一词:async(repo)并开始工作:
repositories.forEach( async(repo) => {
const commits = await getCommits(repo);
displayCommit(commits);
});
#6 楼
async / await是处理promise的机制,我们可以通过两种方式来实现它:functionWhichReturnsPromise()
.then(result => {
console.log(result);
})
.cathc(err => {
console.log(result);
});
,或者我们可以使用await等待诺言首先完全兑现,这意味着它要么被拒绝,要么被解决。
现在,如果我们要在函数内部使用await(等待实现承诺),则必须强制容器函数必须是异步函数,因为我们正在等待异步实现承诺的承诺||。对吗?。
async function getRecipesAw(){
const IDs = await getIds; // returns promise
const recipe = await getRecipe(IDs[2]); // returns promise
return recipe; // returning a promise
}
getRecipesAw().then(result=>{
console.log(result);
}).catch(error=>{
console.log(error);
});
评论
是的,它确实。为了调用异步函数,您将需要在调用方中使用await,并且因为您需要在那里的await,所以该函数mist也将是异步的。基本上,如果您想完全使用异步/等待,则必须在整个应用程序的所有功能上都使用它。
–罗德尼·巴尔巴蒂(Rodney P. Barbati)
9月12日16:43
#7 楼
如果您正在编写Chrome扩展程序,并且在根本上遇到代码错误,则可以使用以下“解决方法”进行修复:async function run() {
// Your async code here
const beers = await fetch("https://api.punkapi.com/v2/beers");
}
run();
基本上,您必须将异步代码包装在
async function
中,然后然后不等待就调用该函数。#8 楼
“等待仅在异步函数中有效”但是为什么呢? “ await”将异步调用显式转换为同步调用,因此,调用方不能是异步的(或异步的)-至少不是因为该调用是在“ await”进行的。
评论
实际上,等待不是等待结果-它会立即返回一个承诺。这正是我试图传达的。如果await实际上是在等待并且没有将控制权返回给调用者,则任何包含await关键字的函数实际上都将无法标记为异步。但除此之外,我们还有任何包含await的函数或调用一个函数,而最终调用包含await的函数必须是异步的。基本上,如果您甚至调用await一次-所有功能都必须标记为异步。
–罗德尼·巴尔巴蒂(Rodney P. Barbati)
2月20日20:08
#9 楼
是的,await / async是一个很棒的概念,但是实现已完全中断。无论出于何种原因,已经实现了await关键字,因此只能在async方法中使用它。实际上,这是一个错误,尽管您在此处看不到它所指的错误。解决此错误的方法是实现await关键字,以便无论调用函数本身是同步还是异步的,都只能用于调用异步函数。
由于该错误,如果在代码中的某个位置使用await调用真正的异步函数,则必须将所有函数标记为异步,并且所有函数调用必须使用await。
这本质上意味着您必须在整个应用程序的所有功能中增加promise的开销,其中大多数不是,而且永远不会是异步的。
如果您实际上认为关于这一点,在函数中使用await应该要求包含await关键字的函数不要同步-这是因为await关键字将暂停在找到await关键字的函数中的处理。如果该函数中的处理被暂停,那么它肯定不是异步的。
因此,对于javascript和ECMAScript的开发人员-请按以下步骤修复await / async实现...
await只能用于CALL异步功能。
await可以出现在任何功能中,同步或异步。
将错误消息从“等待仅在异步函数中有效”更改为“等待只能用于调用异步函数”。
评论
如果愿意,可以将其称为错误,但我不同意。没有诸如“暂停”之类的代码,而是没有一些外部过程(通常是io)的结果而无法完成的代码。此类代码应称为“异步”,因为与单线程的javascript VM相比,许多外部进程应能够同时(非同步)运行。如果您有许多功能需要重构为异步功能,则表明您的许多功能需要外部过程的结果。我认为这完全是规范的。
– Gershom
1月7日20:09
还值得一提的是,限制等待只能用于函数调用的可怕缺点:对于单个外部进程,当该进程完成时,只能在javascript代码中通知单个点。例如,如果出于3个独立目的需要文件的内容,则每个目的都需要独立执行let content = wait readTheFile();。 -这是因为无法等待“文件内容的承诺”,而只能是“读取文件并在读取文件后恢复操作”。
– Gershom
1月7日20:14
好的,我们不要将其称为暂停的代码或无法完成的代码,而是如何阻止等待。麻烦的是-阻塞等待或无法完成的函数是包含await关键字的函数。使用await关键字调用的不是异步函数。因此,绝对不应该将包含await关键字的函数标记为异步-它被阻塞等待,这与异步相反。
–罗德尼·巴尔巴蒂(Rodney P. Barbati)
1月7日20:30
为了使这一点完全清楚,请考虑以下内容-等待通过使异步函数看起来像是同步的(即,它允许我按特定顺序执行操作)来简化异步函数的使用。强制包含await的函数异步是完全错误的名称-您使用await使其变为同步。在所有可能的方式中,包含等待的函数绝对不是异步函数!!!
–罗德尼·巴尔巴蒂(Rodney P. Barbati)
1月7日20:40
@Gershom-听起来很合理。谢谢!
–罗德尼·巴尔巴蒂(Rodney P. Barbati)
2月21日19:59
评论
好吧,问题是等待只能在异步函数中使用。也就是说,await使函数异步,因此必须这样声明。当前错误是什么?
仍然相同,SyntaxError:await仅在异步函数中有效
您需要共享有关代码的更多上下文。
我如何从异步调用返回响应的可能重复项?