首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >快件和异步/等待:我要用试/抓包吗?

快件和异步/等待:我要用试/抓包吗?
EN

Stack Overflow用户
提问于 2018-04-05 04:22:22
回答 3查看 4.5K关注 0票数 8

我有以下代码:

代码语言:javascript
复制
app.post('/routes/passwordReset/:userId', async (req, res, next) => {
  var userId = req.params.userId

  let record = (await vars.connection.queryP('SELECT * FROM contacts WHERE id = ?', userId))[0]

  if (!record) {
    res.status(404).send('')
    return
  }

  // Calculate token and expiry, update database
  var token = require('crypto').randomBytes(48).toString('base64').replace(/[^a-zA-Z0-9]/g, '').substr(0, 28)
  var now = new Date()
  var inOneHour = new Date(now.getTime() + (1 * 1000 * 60 * 60))
  await vars.connection.queryP('UPDATE contacts SET recoverToken = ?, recoverTokenExpiry = ? WHERE id = ?', [ token, inOneHour, userId ])
  res.status(200).send('')
})

如果我创建了一个人为的错误(例如,recoverTokenExpiry的字段人为地太短),我将得到以下结果:

[12:19:55.649] (节点:11919) UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝id: 4):错误: ER_DATA_TOO_LONG:数据太长以至于列'recoverToken‘在第1行

我不知怎么想,如果抛出错误,Express会尝试/捕捉中间件,并调用next(err)。也许不是这样?

那么,我是否应该用try/catch(e)包装每条路由,如果有错误则执行next(e)?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-04-05 04:28:11

快车帮不了你什么忙。它是非常赤裸的骨头。

你有两个选择:

  1. 将所有东西包装在一个try-catch
  2. 编写您自己的错误处理中间件,如docs 这里所示。

调用next()将把reqres传递给堆栈中的下一个中间件。

调用next(err),给它一个Exception对象,将调用堆栈中的任何错误中间件。

在自己的文件中定义错误处理程序:

代码语言:javascript
复制
// error-middleware.js

/**
 * Handler to catch `async` operation errors.
 * Reduces having to write `try-catch` all the time.
 */
exports.catchErrors = action => (req, res, next) => action(req, res).catch(next)

/**
 * Show useful information to client in development.
 */
exports.devErrorHandler = (err, req, res, next) => {
  err.stack = err.stack || ''
  const status = err.status || 500
  const error = { message: err.message }
  res.status(status)
  res.json({ status, error })
}

然后将密码重置逻辑从app.post中移出并进入它自己的专用函数:

代码语言:javascript
复制
// password-controller.js

exports.resetPassword = async (req, res) => {
  // do work
  // ...
}

这使得编写单元测试和明确分离关注点变得更加容易。

接下来,创建您的密码重置路由:

代码语言:javascript
复制
// password-reset-routes.js

const express = require('express')
const router = express.Router()

const passwordController = require('./password-controller')
const { catchErrors } = require('./error-middleware')

router.post('/routes/passwordReset/:userId', catchErrors(passwordController.resetPassword))

module.exports = router

注意,上面定义的控制器是在这里导入和使用的。此外,您还可以看到控制器操作resetPassword是用catchErrors包装的。这避免了一直编写try-catch,任何错误都会被catchErrors中间件捕获。

最后,将其连接到主app.js文件中:

代码语言:javascript
复制
// app.js

const express = require('express')
const { devErrorHandler } = require('./error-middleware')
const passwordResetRoutes = require('./password-reset-routes.js')
const app = express()

app.use(devErrorHandler)
app.use(passwordResetRoutes)

module.exports = app
票数 11
EN

Stack Overflow用户

发布于 2018-04-05 04:32:50

嗯,由于您使用的是等待关键字,这意味着执行流不再是异步的,这就是它失败的原因,是的,每次都必须使用try-catch块。为了避免这种情况,您可以按照异步流的做法,分别使用this ()和catch(),这样您就可以执行如下操作:

代码语言:javascript
复制
...
.then((status)=>{
  res.status(200).send('')
})
.catch((err)=>{
  next(err);
});
...
票数 1
EN

Stack Overflow用户

发布于 2018-04-05 06:44:12

正如其他人所回应的那样,既然你使用的是等待,你就可以把拒绝承诺作为

代码语言:javascript
复制
let record = await vars.connection.queryP('SELECT * FROM contacts WHERE id = ?', userId))[0].then(function () {
     console.log("Promise Resolved");
}).catch((error)=>{
    console.log("Promise rejected")
})
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49664134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档