Maison > interface Web > js tutoriel > le corps du texte

Une brève analyse du middleware de gestion des erreurs d'Express dans Node

青灯夜游
Libérer: 2022-04-07 20:49:30
avant
3162 Les gens l'ont consulté

Cet article vous présentera le middleware de gestion des erreurs d'Express dans Node et présentera la méthode de définition du middleware de gestion des erreurs et de son utilisation avec async/await. J'espère que cela sera utile à tout le monde !

Une brève analyse du middleware de gestion des erreurs d'Express dans Node

Le middleware de gestion des erreurs d'Express vous aide à gérer les erreurs sans répéter le même travail. En supposant que vous gérez les erreurs directement dans le gestionnaire de route Express :

app.put('/user/:id', async (req, res) => {
  let user
  try {
    user = await User.findOneAndUpdate({ _id: req.params.id }, req.body)
  } catch (err) {
    return res.status(err.status || 500).json({ message: err.message })
  }
  return res.json({ user })
})
Copier après la connexion

Le code ci-dessus fonctionne bien, mais que se passe-t-il s'il existe des centaines d'interfaces, alors la logique de gestion des erreurs devient impossible à maintenir car elle est répétée des centaines de fois.

Définir le middleware de gestion des erreurs

Express est divisé en différents types en fonction du nombre de paramètres utilisés par la fonction middleware. La fonction middleware qui accepte 4 paramètres est définie comme middleware de gestion des erreurs et ne sera appelée que lorsqu'une erreur se produit.

const app = require('express')()

app.get('*', function routeHandler() {
  // 此中间件抛出一个错误,Express 将直接转到下一个错误处理程序
  throw new Error('Oops!')
})

app.get('*', (req, res, next) => {
  // 此中间件不是错误处理程序(只有3个参数),Express 将跳过它,因为之前的中间件中存在错误
  console.log('这里不会打印')
})

// 您的函数必须接受 4 个参数,以便 Express 将其视为错误处理中间件。
app.use((err, req, res, next) => {
  res.status(500).json({ message: err.message })
})
Copier après la connexion

Express gérera automatiquement les erreurs de synchronisation pour vous, comme la méthode routeHandler() ci-dessus. Mais Express ne gère pas les erreurs asynchrones. Si une erreur asynchrone se produit, next() doit être appelé. routeHandler() 方法。但是 Express 不处理异步错误。如果出现异步错误,则需要调用 next()

const app = require('express')()

app.get('*', (req, res, next) => {
  // next() 方法告诉 Express 转到链中的下一个中间件。
  // Express 不处理异步错误,因此您需要通过调用 next() 来报告错误。
  setImmediate(() => {
    next(new Error('Oops'))
  })
})

app.use((err, req, res, next) => {
  res.status(500).json({
    message: err.message
  })
})
Copier après la connexion

请记住,Express 中间件是按顺序执行的。您应该在所有其他中间件之后,最后定义错误处理程序。否则,您的错误处理程序将不会被调用:

async/await 一起使用

Express 无法捕获 promise 的异常,Express 在 ES6 之前编写,对于如何处理 async/await 它扔没有好的解决方案。

例如,下面的服务器永远不会成功发送 HTTP 响应,因为 Promise reject 永远不会得到处理:

const app = require('express')()

app.get('*', (req, res, next) => {
  // 报告异步错误必须通过 next()
  return new Promise((resolve, reject) => {
    setImmediate(() => reject(new Error('woops')))
  }).catch(next)
})

app.use((error, req, res, next) => {
  console.log('will not print')
  res.json({ message: error.message })
})

app.listen(3000)
Copier après la connexion

我们可以封装或者使用现有的库来进行捕获。

首先,我们先简单封装一个函数,将 async/await 与 Express 错误处理中间件联系起来。

注意:异步函数会返回 Promise,因此您需要确保 catch() 所有错误并将其传递给 next()

function wrapAsync(fn) {
  return function(req, res, next) {
    fn(req, res, next).catch(next)
  }
}

app.get('*', wrapAsync(async (req, res) => {
  await new Promise(resolve => setTimeout(() => resolve(), 50))
  // Async error!
  throw new Error('woops')
}))
Copier après la connexion

使用第三方库 express-async-errors,一个简单的 ES6 async/await 支持 hack:

require('express-async-errors')
app.get('*', async (req, res, next) => {
  await new Promise((resolve) => setTimeout(() => resolve(), 50))
  throw new Error('woops')
})
Copier après la connexion

最后

Express 错误处理中间件允许您以最大化关注点分离的方式处理错误。您不需要处理业务逻辑中的错误,如果使用 async/await,甚至不需要 try/catchrrreee

N'oubliez pas que le middleware Express est exécuté de manière séquentielle. Vous devez définir les gestionnaires d'erreurs en dernier, après tous les autres middlewares. Sinon, votre gestionnaire d'erreurs ne sera pas appelé :

Utiliser avec async/await Express ne peut pas attraper le code promise> exception, Express a été écrit avant ES6 et il n'existe pas de bonne solution pour gérer async/await qu'il lance. 🎜Par exemple, le serveur suivant n'enverra jamais avec succès la réponse HTTP car la promesse reject ne sera jamais traitée : 🎜rrreee🎜Nous pouvons encapsuler ou utiliser une bibliothèque existante pour effectuer la capture. 🎜🎜Tout d'abord, nous encapsulons simplement une fonction pour connecter async/await au middleware de gestion des erreurs Express. 🎜
🎜🎜Remarque🎜 : Les fonctions asynchrones renvoient Promise, vous devez donc vous assurer de catch() toutes les erreurs et de les transmettre à next(). 🎜
rrreee🎜Utilisez des bibliothèques tierces express-async-errors🎜, un simple hack de support ES6 async/await : 🎜rrreee

Enfin 🎜🎜Intergiciel de gestion des erreurs express Permet vous de gérer les erreurs de manière à maximiser la séparation des préoccupations. Vous n'avez pas besoin de gérer les erreurs dans votre logique métier, ni même de try/catch si vous utilisez async/await. Ces erreurs apparaîtront dans votre gestionnaire d'erreurs, qui pourra alors décider comment répondre à la demande. Assurez-vous de profiter de cette fonctionnalité puissante dans votre prochaine application Express ! 🎜🎜Pour plus de connaissances sur les nœuds, veuillez visiter : 🎜tutoriel Nodejs🎜 ! 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal