我在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;

我遇到了错误

”在异步函数中有效”

问题是什么?

评论

好吧,问题是等待只能在异步函数中使用。也就是说,await使函数异步,因此必须这样声明。

当前错误是什么?

仍然相同,SyntaxError:await仅在异步函数中有效

您需要共享有关代码的更多上下文。

我如何从异步调用返回响应的可能重复项?

#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')
}


说明:

在您的问题中,您要导入一个本质上为methodasynchronous,它将并行执行。但是,在您尝试执行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