繁体   English   中英

如何使用函数使用异步等待

[英]How to use async await using functions

我在 Nodejs 上使用 express 制作了 api。
但我不确定我是否很好地使用了异步等待。

module.search = async(req, res) => {
    async function searchJibun(arg) {
        const resultJibun = await axios.get(
          'https://apis.com/code',
          {
            headers: {
              'KEY-ID': process.env.N_KEY_ID,
              'KEY': process.env.N_KEY
            },
            params: {
              query: arg
            }
          }
        );

        return resultJibun;
      }

      const { query } = req.body;
      const searchResult = [];
      let result = '';

      try {
        result = await searchJibun(query);
      } catch (error) {
        return res.status(200).json({
          success: false,
          code: 500,
          msg: 'Internal Server Error(1)',
          err: error
        });
      }
}

在这一行中,如果我输入“await”,效果是否良好? 还是由于我完全错误地使用了异步等待而导致结果相同?

result = await searchJibun(query);

result = searchJibun(query);

非常感谢您的阅读。

两者之间肯定有区别:

result = await searchJibun(query);

result = searchJibun(query);

为简单起见,将await视为一个特殊的 function 从 Promise 解包值,并将值async打包到 Promise 中。

在我谈论这两个语句有何不同之前,您需要了解async pack 的价值。

为了让事情更清楚,我将使用 TypeScript 来解释这个概念。


异步

假设您有一个将数字翻倍的 function。

function double_v1(x: number) { 
    return x * 2; 
}

上面 function 的返回类型将是number 因此,从类型系统的角度来看,以下表达式是有效的。

double_v1(2) + 3

但是,如果您将async放在 function 前面,则返回类型将更改为Promise<number> ,即使您没有在代码中的任何位置提及Promise一词。

async function double_v2(x: number) {
    return x * 2;
}

本质上,上面的代码与下面的代码是等价的:

function double_v2(x: number) {
    return Promise.resolve(x * 2);
}

并且下面的表达式将是无效的,因为你不能用 Promise 添加数字。

double_v2(2) + 3 // type error

等待

如前所述, await用于从 Promise 中解压值。 这意味着如果表达式的类型为Promise<T> ,则await会将表达式解包为T类型。

例如, double_v2 function 的返回类型为Promise<number> ,因此result的类型为number

const result = await double_v2(3)

如果从语句中删除awaitresult类型将改为Promise<number>

但是,请注意,反过来是不正确的。 如果你await一个非 Promise 表达式,你将返回相同的类型,这意味着下面的两个语句是等价的,因为double_v1的返回类型不是 Promise 而是数字。

// Equivalent
result = await double_v1(3)
result = double_v1(3)

结论

searchJibun function 是用async关键字标记的,这意味着它必须返回 Promise,因此在调用searchJibun时使用await将解包 Promise,因此以下语句不等效。

result = await searchJibun(query);  // type of result will be T

result = searchJibun(query);        // type of result will be Promise<T>

额外说明

asyncawait实际上是基于提升(又名打包)的概念。 在这种情况下, asyncliftawaitunlift

在 arrays 的情况下,方括号是lift ,索引运算符是unlift

例如, 2的类型是number ,但是当你用像这样的方括号[2]将它括起来时,你会将类型提升Array<number>

解除数组,您可以使用像这样的索引运算符[2][0] ,这个表达式将是number的类型。

Promise的情况下, .resolvelift.thenunlift 例如,您可以通过编写Promise.resolve(e)将类型为T的表达式e的类型提升为Promise<T> ,然后您可以使用myPromise.then(e => {...})取消它

最后,要真正理解asyncawait ,你只需要意识到它们只是提升和解除Promise的语法糖。

在没有糖的世界中,上述操作本可以以更统一的风格编写。

// Arrays
myArray = liftAsArray(1, 2, 3)
firstValue = unliftArray(myArray, 0)

// Promises
myPromise = liftAsPromise(1)
value = unliftPromise(myPromise)

尽管这种编写代码的风格是一致的,但它更冗长,因此更难快速阅读。

P/S: async/await不是纯粹的语法糖,它们的存在是为了让编译器对你的代码执行一些魔法,这就是为什么使用async/awaitPromises之间存在性能差异的原因

只要您的searchJibun() function 是用async定义的,您就需要等待带有await的响应

在您的异步函数中,您将不得不使用await来接收您的 api 响应

我建议您阅读这篇文章以更好地理解

暂无
暂无

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

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