首页 > 语言 > JavaScript > 正文

详解Node.js中的Async和Await函数

2024-05-06 15:21:38
字体:
来源:转载
供稿:网友

在本文中,你将学习如何使用Node.js中的async函数(async/await)来简化callback或Promise.

异步语言结构在其他语言中已经存在了,像c#的async/await、Kotlin的coroutines、go的goroutines,随着Node.js 8的发布,期待已久的async函数也在其中默认实现了。

Node中的async函数是什么?

当函数声明为一个Async函数它会返回一个 AsyncFunction 对象,它们类似于 Generator 因为执可以被暂停。唯一的区别是它们返回的是 Promise 而不是 { value: any, done: Boolean } 对象。不过它们还是非常相似,你可以使用 co 包来获取同样的功能。

在async函数中,可以等待 Promise 完成或捕获它拒绝的原因。

如果你要在Promise中实现一些自己的逻辑的话

function handler (req, res) { return request('https://user-handler-service') .catch((err) => {  logger.error('Http error', err)  error.logged = true  throw err }) .then((response) => Mongo.findOne({ user: response.body.user })) .catch((err) => {  !error.logged && logger.error('Mongo error', err)  error.logged = true  throw err }) .then((document) => executeLogic(req, res, document)) .catch((err) => {  !error.logged && console.error(err)  res.status(500).send() })}

可以使用 async/await 让这个代码看起来像同步执行的代码

async function handler (req, res) { let response try { response = await request('https://user-handler-service')  } catch (err) { logger.error('Http error', err) return res.status(500).send() } let document try { document = await Mongo.findOne({ user: response.body.user }) } catch (err) { logger.error('Mongo error', err) return res.status(500).send() } executeLogic(document, req, res)}

在老的v8版本中,如果有有个 promise 的拒绝没有被处理你会得到一个警告,可以不用创建一个拒绝错误监听函数。然而,建议在这种情况下退出你的应用程序。因为当你不处理错误时,应用程序处于一个未知的状态。

process.on('unhandledRejection', (err) => {  console.error(err) process.exit(1)})

async函数模式

在处理异步操作时,有很多例子让他们就像处理同步代码一样。如果使用 Promise 或 callbacks 来解决问题时需要使用很复杂的模式或者外部库。

当需要再循环中使用异步获取数据或使用 if-else 条件时就是一种很复杂的情况。

指数回退机制

使用 Promise 实现回退逻辑相当笨拙

function requestWithRetry (url, retryCount) { if (retryCount) { return new Promise((resolve, reject) => {  const timeout = Math.pow(2, retryCount)  setTimeout(() => {  console.log('Waiting', timeout, 'ms')  _requestWithRetry(url, retryCount)   .then(resolve)   .catch(reject)  }, timeout) }) } else { return _requestWithRetry(url, 0) }}function _requestWithRetry (url, retryCount) { return request(url, retryCount) .catch((err) => {  if (err.statusCode && err.statusCode >= 500) {  console.log('Retrying', err.message, retryCount)  return requestWithRetry(url, ++retryCount)  }  throw err })}requestWithRetry('http://localhost:3000') .then((res) => { console.log(res) }) .catch(err => { console.error(err) })            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选