理解 Node JS 中的 async/await
Posted
技术标签:
【中文标题】理解 Node JS 中的 async/await【英文标题】:Understanding async/await on NodeJS 【发布时间】:2017-11-14 16:39:47 【问题描述】:我认为我对它的理解可能会受到我使用 .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',
,
]);
;
;
此代码不起作用,浏览器不断加载和加载,从不显示任何内容。
我基于this SO answer 构建的getUser
函数和控制器方法,基于我对它如何工作的(错误的)理解,所以我想要一些澄清和更正:
1.我什么时候应该使用await
?
据我了解,您应该在 async
函数调用之前使用 await
。它是否正确?另外,为什么我可以在返回 promise 的非异步函数之前调用 await?
2。我应该什么时候使用async
?
据我了解,您将函数标记为async
,以便可以使用await
关键字调用它。它是否正确?另外,[为什么]我必须将我的 await getUsers(5000)
调用包装在匿名异步函数中?
【问题讨论】:
不要将东西包装在异步匿名函数中,这在您的代码中也永远不会执行。而是使索引函数异步并删除函数包装并返回 res.json 【参考方案1】:解几个疑惑——
-
您可以将
await
与任何返回承诺的函数一起使用。您等待的函数不一定是async
。
当您想在函数中使用await
关键字时,您应该使用async
函数。如果您不打算在函数中使用 await
关键字,那么您不需要创建该函数 async
。
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 被解决(拒绝或履行)
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 关键字使异步编程表现得像同步编程。因此,您的应用程序更容易理解。以上是关于理解 Node JS 中的 async/await的主要内容,如果未能解决你的问题,请参考以下文章
node.js异步控制流程 回调,事件,promise和async/await
Node.js 7 的 async await 终于来了,不过怎么觉得没啥用