繁体   English   中英

await 只在 async 中有效 function

[英]await is only valid in async function

我在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 is only valid in async function

问题是什么?

该错误不是指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)

`return await` 是否存在性能问题?

要使用await ,它的执行上下文需要本质上是async

正如它所说,您需要定义executing context的性质,您愿意在任何事情之前await任务。

只需将async放在将执行async任务的fn声明之前。

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

解释:

在您的问题中,您正在导入一个本质上是asynchronous的并且将并行执行的method 但是您尝试执行该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/task-returning 方法/函数,并且async将方法/函数标记为能够使用 await。

此外,如果您熟悉promises ,那么await实际上正在执行相同的 promise/resolve 过程。 创建一个承诺链并在resolve回调中执行您的下一个任务。

有关更多信息,您可以参考MDN 文档

当我收到这个错误时,原来我在我的“异步”函数中调用了映射函数,所以这个错误消息实际上是指映射函数没有被标记为“异步”。 我通过从 map 函数中提取“await”调用并提出其他一些获得预期行为的方法来解决这个问题。

var myfunction = async function(x,y) {
    ....
    someArray.map(someVariable => { // <- This was the function giving the error
        return await someFunction(someVariable);
    });
}

我遇到了同样的问题,下面的代码块给出了同样的错误信息:

repositories.forEach( repo => {
        const commits = await getCommits(repo);
        displayCommit(commits);
});

问题是方法 getCommits() 是异步的,但我传递给它的参数 repo 也是由 Promise 生成的。 所以,我不得不像这样添加 async 这个词:async(repo) 并且它开始工作:

repositories.forEach( async(repo) => {
        const commits = await getCommits(repo);
        displayCommit(commits);
});

如果您正在编写 Chrome 扩展程序并且您的代码在根目录中出现此错误,您可以使用以下“解决方法”修复它:

async function run() {
    // Your async code here
    const beers = await fetch("https://api.punkapi.com/v2/beers");
}

run();

基本上,您必须将异步代码包装在async function中,然后在不等待的情况下调用该函数。

当前的async / await实现仅支持async函数中的await关键字 更改您的start函数签名,以便您可以在start中使用await

 var start = async function(a, b) {

 }

对于那些感兴趣的人,顶级await的提案目前处于第 2 阶段: https ://github.com/tc39/proposal-top-level-await

async/await 是处理 promise 的机制,有两种方法可以做到

functionWhichReturnsPromise()
            .then(result => {
                console.log(result);
            })
            .cathc(err => {
                console.log(result);

            });

或者我们可以使用 await 来等待 promise 先完整提交它,这意味着它要么被拒绝,要么被解决。

现在,如果我们想在函数中使用await (等待一个 promise 实现),容器函数必须是一个异步函数,因为我们正在等待一个异步实现的 promise || 有道理吗?

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);
        });

在这篇不错的文章中找到下面的代码: HTTP requests in Node using Axios

const axios = require('axios')

const getBreeds = async () => {
  try {
    return await axios.get('https://dog.ceo/api/breeds/list/all')
  } catch (error) {
    console.error(error)
  }
}

const countBreeds = async () => {
  const breeds = await getBreeds()

  if (breeds.data.message) {
    console.log(`Got ${Object.entries(breeds.data.message).length} breeds`)
  }
}

countBreeds()

或使用承诺:

const axios = require('axios')

const getBreeds = () => {
  try {
    return axios.get('https://dog.ceo/api/breeds/list/all')
  } catch (error) {
    console.error(error)
  }
}

const countBreeds = async () => {
  const breeds = getBreeds()
    .then(response => {
      if (response.data.message) {
        console.log(
          `Got ${Object.entries(response.data.message).length} breeds`
        )
      }
    })
    .catch(error => {
      console.log(error)
    })
}

countBreeds()

如果您在foreach中调用了异步函数,请将其更新为for 循环

这在一个文件中有效..

看起来 await 仅应用于必须是异步的本地函数..

我现在也在为更复杂的结构和不同文件之间的关系而苦苦挣扎。 这就是我制作这个小测试代码的原因。

编辑:我忘了说我正在使用node.js .. sry。 我没有明确的问题。 只是认为这可能对讨论有所帮助..

    function helper(callback){



    function doA(){

        var array = ["a ","b ","c "];

        var alphabet = "";

        return new Promise(function (resolve, reject) {

            array.forEach(function(key,index){

            alphabet += key;

                if (index == array.length - 1){

                    resolve(alphabet);

                };

            });

        });

    };



    function doB(){

        var a = "well done!";

        return a;

    };



    async function make() {

        var alphabet = await doA();
        var appreciate = doB();

        callback(alphabet+appreciate);

    };

    make();

};

helper(function(message){

    console.log(message);

});

Express中的一个常见问题:

警告可以参考function,或者你叫它的地方。

快递项目往往看起来像这样:

app.post('/foo', ensureLoggedIn("/join"), (req, res) => {
    const facts = await db.lookup(something)
    res.redirect('/')
})

请注意 function 的=>箭头 function 语法。

问题实际上不在 db.lookup 调用中,而在 Express item中。

需要是:

app.post('/foo', ensureLoggedIn("/join"), async function (req, res) {
    const facts = await db.lookup(something)
    res.redirect('/')
})

基本上,去掉=>并添加async function

在后来的nodejs(>=16)中,允许top await with { "type": "module" }package.json中指定

“等待仅在异步函数中有效”

但为什么? 'await' 显式地将异步调用转换为同步调用,因此调用者不能是异步的(或异步的) - 至少不是因为调用是在 'await' 进行的。

是的,await / async 是一个很棒的概念,但是实现完全被破坏了。

无论出于何种原因,await 关键字已被实现,因此它只能在异步方法中使用。 这实际上是一个错误,尽管您不会在任何地方看到它被这样称呼,但就在这里。 此错误的修复将是实现 await 关键字,以便它只能用于调用异步函数,而不管调用函数本身是同步的还是异步的。

由于此错误,如果您在代码中的某处使用 await 调用真正的异步函数,则必须将所有函数标记为异步,并且所有函数调用都必须使用 await。

这实质上意味着您必须将承诺的开销添加到整个应用程序中的所有函数中,其中大多数不是并且永远不会是异步的。

如果您真的考虑一下,在函数中使用 await 应该要求包含 await 关键字的函数不能异步 - 这是因为 await 关键字将在找到 await 关键字的函数中暂停处理。 如果该函数中的处理被暂停,那么它肯定不是异步的。

因此,对于 javascript 和 ECMAScript 的开发人员 - 请按如下方式修复 await/async 实现...

  • await 只能用于调用异步函数。
  • await 可以出现在任何类型的函数中,同步的或异步的。
  • 将错误消息从“await 仅在异步函数中有效”更改为“await 只能用于调用异步函数”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM