为什么一个函数在调用另一个异步函数时是异步的?

时间:2021-05-18 01:47:28

标签: javascript async-await

我以为我了解如何使用 async 和 await,直到看到以下代码片段。

所以有一个 onInput 事件处理函数附加到电影输入文本框。其中称为 fetchData 异步函数,它使用 await 关键字来等待来自 axios.get 函数的结果。

我的问题是,为什么我们需要使 onInput 函数也异步?我的意思是,fetchData 函数是异步的。这意味着,它将等到 axios.get 被解析,并且执行将暂停直到 axios.get 被解析。所以当行 const movies = fetchData(event.target.value);执行,将执行 fetchData 函数,该函数将在 await axios.get 语句上暂停。那么为什么我们需要在调用 fetchData 时使用 await 并使 onInput 异步??

const fetchData = async(searchTerm)=>{
    const results =  await axios.get('http://www.omdbapi.com/', {
    params:{
        apikey:'d9835cc5',
        s: searchTerm
        }

    });
    return results.data.Search;
}

    const movieInput = document.querySelector('input');
    
    
    const onInput = async event => {
        const movies = await fetchData(event.target.value);
        console.log(movies);
    }
    
    movieInput.addEventListener('input', onInput);

3 个答案:

答案 0 :(得分:3)

<块引用>

我的意思是,fetchData 函数是异步的。这意味着,它会等到 axios.get 被解析,然后执行将暂停,直到 axios.get 被解析。

这个概念隐藏了很多可能令人困惑的细节,例如使用回调函数恢复暂停的执行。

  • async 函数不会暂停调用者的执行。

    相反,它们返回一个承诺,该承诺将使用执行 async 函数体在语法上返回的值进行解析。需要明确的是,显然从 async 函数体内返回的值不会直接返回给调用者 - 调用者会得到一个承诺。

  • 执行时,await operator 设置回调,以便其操作数承诺何时解决。在将当前执行上下文存储在内存中并返回到事件循环之前,它有效地调用其 promise 操作数的 then 方法以提供一组 onfulfilledonrejected 回调。

    当它收到来自 promise 结算的回调时,await 运算符会恢复它之前保存的执行上下文。如果等待的承诺被拒绝,await 会抛出拒绝原因。如果已完成,await 将继续执行并返回作为执行 await 运算符的结果的承诺的已完成值。

现在历史上 await 从来都不是保留关键字 - 在 ES3 中没有提及,在 ES6 (ECMAScript 2015) 中未来保留关键字,而是在 2021 年 5 月的 ECMAscript 当前草案中的保留字。

因此,为了保持与网络代码的兼容性,await 仅在出现在 async 函数中时才被识别为运算符 - 将其保留为 async 之外的标识符函数体。

同样,async 关键字在历史上也不是保留的,但通过要求将其用于在以前版本的 JavaScript 中会产生意外标识符错误的位置,可以在没有可比性问题的情况下引入。含义在 function 关键字之前或箭头函数表达式之前。

最后,您需要将 onInput 声明为 async 函数,因为 await 在其主体中用作运算符。如果没有 async 声明,await 将被视为标识符而不是运算符的名称。

附带说明,onInput 返回的承诺被丢弃,并可能在当前形式中生成未捕获的承诺拒绝错误。


为了回答“为什么 await 完全需要在 onInput 函数中使用?”这个稍微不同的问题,从 fetchData 返回的值是一个挂起的承诺。为了将movies设置为results.data.Search内获得的fetchData值,需要等待返回promise的fulfiled值。使用 async/await 是这样做的一种方法。另一种方法是通过调用 fetchData 方法向从 then 返回的承诺添加履行处理程序。

答案 1 :(得分:1)

您在 await 中使用了 inInput 运算符。 JavaScript 规则是使用 await 的函数必须是异步的,因此 inInput 也必须是异步的。看看这个答案:https://stackoverflow.com/a/56685416/13357440

此外,MDN 有有用的信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

答案 2 :(得分:0)

通常,您希望在程序的其余部分运行时执行 API 调用,因此 onInput 将是异步的。此外,javascript 要求 await 位于 async 函数内,因此代码也只是遵循其标准和规则。通常,一旦顶级是异步的,它内部的所有内容都只是遵循该结构。可以在 here 中找到更多信息。