如何使用异步等待功能

时间:2019-09-29 12:29:33

标签: javascript node.js

我在Node.js上使用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);

非常感谢您的阅读。

2 个答案:

答案 0 :(得分:2)

两者之间肯定有区别

result = await searchJibun(query);

result = searchJibun(query);

为简单起见,将await视为从Promise拆包价值的特殊功能,并将async打包为Promise的价值。

在讨论这两个语句有何不同之前,您需要了解async打包值的方式。

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


异步

假设您有一个将数字加倍的函数。

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

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

double_v1(2) + 3

但是,即使在代码中的任何地方都没有提到async字样,如果将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函数的返回类型为Promise<number>,因此result的类型为number

const result = await double_v2(3)

如果从语句中删除await,则result的类型将变为Promise<number>

但是,请注意,反之亦然。如果您await使用非Promise表达式,则将返回相同的类型,这意味着以下两个语句是等效的,因为double_v1的返回类型不是Promise而是数字。

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

结论

searchJibun函数用async关键字标记,这意味着它必须返回Promise,因此在调用await时使用searchJibun将解压缩Promise,因此以下内容声明不相同。

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

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

额外笔记

asyncawait实际上是基于提起(也称为包装)的概念。在这种情况下,async lift ,而await unlift

对于数组,方括号为 lift ,而索引运算符为 unlift

例如,2的类型为number,但是当您用[2]这样的方括号将其包围时,您将 lift 变成{ {1}}。

取消一个数组,请使用像Array<number>这样的索引运算符,该表达式的类型为[2][0]

number的情况下,Promise lift ,而.resolve unlift 。例如,您可以通过编写.then将类型e的表达式T的类型提升为Promise<T>,然后用Promise.resolve(e) < / p>

最后,要真正理解myPromise.then(e => {...})async,您只需要意识到它们只是 lifting unlifting 承诺。

在一个无糖的世界中,上面的操作原本可以用更统一的样式编写。

await

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

P / S:// Arrays myArray = liftAsArray(1, 2, 3) firstValue = unliftArray(myArray, 0) // Promises myPromise = liftAsPromise(1) value = unliftPromise(myPromise) 并不是纯粹的语法糖,它们存在的目的是使编译器可以对您的代码执行一些魔术,这就是为什么在使用async/awaitasync/await之间存在性能差异的原因< / p>

答案 1 :(得分:1)

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

在异步功能中,您将必须使用await来接收api响应

我建议您阅读article以便更好地理解