了解 NodeJS 上的异步/等待

IT技术 javascript node.js asynchronous async-await
2021-03-09 02:16:03

我认为我对它的理解可能会受到我对.NET经验的影响async/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',
      },
    ]);
  };
};

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

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

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

据我了解,您应该awaitasync函数调用之前使用这个对吗?另外,为什么我可以在返回Promise的非异步函数之前调用 await ?

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

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

4个回答

澄清几个疑惑——

  1. 您可以await与任何返回Promise的函数一起使用您正在等待的功能async不一定是。
  2. async当您想await在该函数中使用关键字时,您应该使用函数。如果您不打算await在函数内使用关键字,那么您不需要创建该 function async
  3. async函数默认返回一个promise。这就是你能够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(这是一个返回Promise的函数)与 express 路由器挂钩,其中一个router.get变体接受Promise。这个对吗?
2021-04-27 02:16:03
是的,在 Express 中,您可以像这样使用它 - router.get('/users', index)
2021-05-07 02:16:03

Javascript 中的异步函数

async关键字变成一个普通JS函数声明为异步函数声明:

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

异步函数返回一个 Promise:

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

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

  • . 当promise fullfillsawait表达式的值就是fullfill 的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实现)时,异步函数是一个有用的工具。例如,当您的第二个Promise需要您的第一个Promise将提供的数据时。您现在可以方便地使用await关键字首先接收 promise 1 中的数据,然后将此数据作为参数传递给 promise 2。

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

说得好:换句话说,异步函数可以通过 await 关键字使异步编程表现得像同步编程。因此,您的应用程序更易于理解。
2021-04-23 02:16:03

您可以awaitasync函数中进行任何Promise之后的代码await将在您等待的Promise完成后执行。

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

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

async await 只是 promise 的语法糖。

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

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

如果您使用 promises land 语法,那就是确切的事情:

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

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

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

let value = await myPromisifiedFunction(); 

当您计划在您的函数中使用 await 时,您应该使用 async 关键字标记您的函数(如在 c# 中)

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