使用 nodejs + express 在服务器端和客户端处理错误的最佳方法是什么

IT技术 javascript node.js reactjs express try-catch
2021-05-24 18:24:05

我想知道处理响应中错误的最佳方法 - 请求。我有一条收到请求的路线:

app.get('/getInfo', function (req, res, next) {
    let obj = {}
    try {
        obj = { 
            ...                
            date: lastUpdatedDate('./utils/appVersion.js'),
            ...
        }
        res.status(200).send(obj)
    } catch (error) {
        console.log(error.message)
        res.send({error: "The data wasn't load"})
    }       
})

以及发出请求的这个函数

getInfo () {
    axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
        this.appInfoHandler(resp.data)
      })
      .catch(function (error) {    
        console.log(error)
      })
  }

如果错误发生在服务器端,处理错误的最佳方法是什么?让我们假设在此代码块中目录不存在:lastUpdatedDate('./directoreyDoesntExists/appVersion.js'),

所以我的代码去catch块。

我应该发送这样的错误:

res.send({error: "The data wasn't load"})

我应该设置这样的状态吗?

  res.status(500).send({error: "The data wasn't load"})

或者我应该使用不同的状态代码设置状态?

基于此,在我的前端方法中处理它getInfo()以获取错误并在 Web 界面上显示错误消息的最佳方法是什么

我应该像这样if else.then做一个吗?

 getInfo () {
      axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
            if(resp.status === 200){
                 this.appInfoHandler(resp.data)
            }else if (resp.status === 400){
                  //print error message on web interface
            }else if (resp.status === 500){
                  //print error message on web interface
          })
          .catch(function (error) {    
            console.log(error)
          })

或者我应该catch像这样直接在块中处理这个错误

getInfo () {
    axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
        this.appInfoHandler(resp.data)
      })
      .catch(function (error) {    
        //print error message on web interface
      })
  }
4个回答

对于这种情况

res.send({error: "The data wasn't load"}) 

对比

res.status(500).send({error: "The data wasn't load"})

发送状态只是更详细,但两者都可以。检查设置响应状态和 JSON 内容的正确方法

对于这种情况,取决于您的需要

then(resp => {
            if(resp.status === 200){
                 this.appInfoHandler(resp.data)
            }else if (resp.status === 400){
                  //print error message on web interface
            }else if (resp.status === 500){
                  //print error message on web interface
          })
          .catch(function (error) {    
            console.log(error)
          })

对比

getInfo () {
    axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
        this.appInfoHandler(resp.data)
      })
      .catch(function (error) {    
        //print error message on web interface
      })
  }

您可以处理将它们发送到 catch 块的所有错误

else if (resp.status === 400){
                  //print error message on web interface

不在此处打印错误,而是抛出一个新错误,将其发送到 catch 块

throw new ApiError("UserNotFount",400,"not found");
throw new Error('Error 400, not found');

对于这种情况

res.send({error: "The data wasn't load"}) 

对比

res.status(500).send({error: "The data wasn't load"})

我建议发送错误和状态代码,因为这对客户端来说更具描述性。

对于第二种情况

getInfo () {
      axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
            if(resp.status === 200){
                 this.appInfoHandler(resp.data)
            }else if (resp.status === 400){
                  //print error message on web interface
            }else if (resp.status === 500){
                  //print error message on web interface
          })
          .catch(function (error) {    
            console.log(error)
          })

对比

getInfo () {
    axios.get(process.env.REACT_APP_HOST + '/getInfo')
      .then(resp => {
        this.appInfoHandler(resp.data)
      })
      .catch(function (error) {    
        //print error message on web interface
      })
  }

在这种情况下,我建议在出现错误时直接使用 catch 块,因为响应状态取决于错误而不是相反

作为使用 REST Api 的初学者,您应该查看指南 - 微软的指南非常合法:https : //docs.microsoft.com/en-us/azure/architecture/best-practices/api-design

基本上,你需要为每个请求返回正确的HTTP代码,看看https://http.cat/ - 例如如果请求格式错误,返回400,如果用户未经授权返回401:

if (!req.body.name) {
  res.status(400).send({ error: 'missing user name' }); // 400 bad request
}
const user = getUser(req.body.name, req.body.pass);

if(!user) {
  res.status(401).send({ error: 'user does not exist' }); // 401 unauthorized
}

try {
  const token = createToken(user);
  // better to set a cookie
  res.status(200).send({ token }); // 200 success
} catch(e) {
  res.status(500).send({ erroe: e.message }); // 500 internal error
}

if(isTeapot) {
  res.status(418).send({ error: 'I can only make tea' }); // 418 teapot, totally real
}

为了让事情变得更容易,有很多库可以帮助您生成更好的错误消息并更好地处理错误,我最喜欢的一个是庆祝

除了 200 之外的任何状态代码都意味着不成功,因此您不需要使用那些 if-else 语句。更好的选择是捕获错误并按原样发送响应。好处是您会收到没有硬编码状态代码的错误类型。(例如,我们将这里的状态码设为 400 不成功)

 .catch(function (error) {    
        //print error message on web interface
        res.status(400).send(JSON.stringify(error, undefined, 2));
      });

通过使用 stringify 方法,您还可以在控制台上打印确切的错误。

.catch(function (error) {    
            console.log(JSON.stringify(error, undefined, 2));
          });

这里的stringify方法中的参数是:

  1. 错误对象

  2. 未定义:包含用于过滤对象中键的键的数组(此处为错误)。此数组中存在的所有键只是未过滤掉的键。

  3. 2:用于在对象表示中引入空格