【问题标题】:Understanding async/await on NodeJS理解 Node JS 中的 async/await
【发布时间】:2017-11-14 16:39:47
【问题描述】:

我认为我对它的理解可能会受到我使用 .NETasync/await 的经验的影响,所以我想要一些代码示例:

我正在尝试让快速控制器在返回响应之前等待 5 秒:

const getUsers = async (ms) => {
  var wait = ms => new Promise(resolve => setTimeout(resolve, ms));

  await wait(ms);
};


export const index = (req, res) => {
  async () => {
    await getUsers(5000);

    res.json([
      {
        id: 1,
        name: 'John Doe',
      },
      { id: 2,
        name: 'Jane Doe',
      },
    ]);
  };
};

此代码不起作用,浏览器不断加载和加载,从不显示任何内容。

我基于this SO answer 构建的getUser 函数和控制器方法,基于我对它如何工作的(错误的)理解,所以我想要一些澄清和更正:

1.我什么时候应该使用await

据我了解,您应该在 async 函数调用之前使用 await。它是否正确?另外,为什么我可以在返回 promise 的非异步函数之前调用 await?

2。我应该什么时候使用async

据我了解,您将函数标记为async,以便可以使用await 关键字调用它。它是否正确?另外,[为什么]我必须将我的 await getUsers(5000) 调用包装在匿名异步函数中?

【问题讨论】:

  • 不要将东西包装在异步匿名函数中,这在您的代码中也永远不会执行。而是使索引函数异步并删除函数包装并返回 res.json

标签: javascript node.js asynchronous async-await


【解决方案1】:

解几个疑惑——

  1. 您可以将await 与任何返回承诺的函数一起使用。您等待的函数不一定是async
  2. 当您想在函数中使用await 关键字时,您应该使用async 函数。如果您不打算在函数中使用 await 关键字,那么您不需要创建该函数 async
  3. async 函数默认返回一个承诺。这就是您能够await async 函数的原因。

来自MDN -

当一个异步函数被调用时,它会返回一个 Promise。

就你的代码而言,它可以这样写 -

const getUsers = (ms) => { // No need to make this async
    return new Promise(resolve => setTimeout(resolve, ms));
};

// this function is async as we need to use await inside it
export const index = async (req, res) => {
    await getUsers(5000);

    res.json([
      {
        id: 1,
        name: 'John Doe',
      },
      { id: 2,
        name: 'Jane Doe',
      },
    ]);
};

【讨论】:

  • 这个解释很清楚。现在,剩下的就是将导出的异步函数 index(这是一个返回承诺的函数)与 express 路由器连接起来,其中一个接受承诺的 router.get 变体。这是正确的吗?
  • 是的,在 Express 中你可以像这样使用它 - router.get('/users', index)
【解决方案2】:

async await 只是 Promise 的语法糖。

当您希望代码在函数完成时运行时,您可以像使用 Promise 一样使用它们。

async function asyncOperation(callback) {
    const response = await asyncStep1();
    return await asyncStep2(response);
}

如果你使用 promises 的语法,那是正确的:

function asyncOperation() {
  return asyncStep1(...)
    .then(asyncStep2(...));
}

新的 async/await 语法允许您仍然使用 Promises,但它消除了为链接的 then() 方法提供回调的需要。

回调直接从异步函数返回,就像它是一个同步阻塞函数一样。

let value = await myPromisifiedFunction(); 

当你计划在你的函数中使用 await 时,你应该用 async 关键字标记你的函数(就像在 c# 中一样)

您不必将 getUsers 创建为匿名函数。

【讨论】:

    【解决方案3】:

    您可以在async 函数中await 任何承诺。 await后面的代码会在你等待的promise完成后执行。

    这是经典 JavaScript 回调的绝佳替代方案。

    我写了一篇关于它的博客 -> https://github.com/Gameye/js-async我希望这对你有帮助!

    【讨论】:

      【解决方案4】:

      Javascript 中的异步函数

      async 关键字将常规 JS 函数声明转换为异步函数声明:

      function syncFunc {// dostuff}
      async function asyncFunc {// dostuff} // the async keyword is placed before the function keyword
      

      一个异步函数返回一个 Promise:

      • 当 async 函数返回值时,Promise 将使用返回值进行解析。
      • 当异步函数抛出异常或某个值时,Promise 将被抛出的值拒绝。

      在异步函数中,您可以使用 await 关键字。 await 放置在 promise 之前会导致异步函数暂停,直到 promise 被解决(拒绝或履行)

      • 。当 Promise 完成时 await 表达式的值就是完成的 Promise 的值。
      • 当 promise 被拒绝时,await 表达式抛出被拒绝的值。

      示例:

      function makePromise(x) { 
          return new Promise(resolve => {
            setTimeout(() => {
              resolve(x);
            }, 1000);
          });
        }
        
        async function asyncFunc() {
          var x = await makePromise(1); // the function is paused here until the promise is fulfilled
          console.log(x); // logs 1
          return x;
        }
        
        const returnedProm = asyncFunc(); // the async func returns a promise
      
      
        returnedProm.then((x) => console.log(x));
        // This promise is fulfilled with the return value from the async func, so this logs 1

      何时使用异步函数:

      当您有多个相互依赖的异步操作(作为 Promise 实现)时,异步函数是一个有用的工具。例如,当您的第二个承诺需要您的第一个承诺将提供的数据时。您现在可以方便地使用await 关键字首先接收promise 1 中的数据,然后将此数据作为参数传递给promise 2。

      换句话说,async 函数可以通过await 关键字使异步编程表现得像同步编程一样。因此,您的应用程序更容易理解。

      【讨论】:

      • 漂亮地说:换句话说,async 函数可以通过 await 关键字使异步编程表现得像同步编程。因此,您的应用程序更容易理解。
      猜你喜欢
      • 1970-01-01
      • 2018-04-12
      • 2020-12-19
      • 1970-01-01
      • 2020-03-25
      • 1970-01-01
      • 2018-10-13
      • 2021-05-22
      • 1970-01-01
      相关资源
      最近更新 更多