【问题标题】:What's the best way to deal with an error in the server side and in the client side using nodejs + express使用nodejs + express处理服务器端和客户端错误的最佳方法是什么
【发布时间】:2019-11-08 09:28:36
【问题描述】:

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

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 界面上显示错误消息的最佳方法是什么?

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

 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
      })
  }

【问题讨论】:

    标签: javascript node.js reactjs express try-catch


    【解决方案1】:

    对于这种情况

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

    对比

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

    发送状态更详细,但两者都可以。 检查Proper way to set response status and JSON content

    对于这种情况,取决于你需要什么

    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.status(500).send({error: "The data wasn't load"})这样在服务器端发送响应时,它会在前端捕获块。那么,应该以状态 200 发送它吗? – mr.abdo 刚刚编辑
    • 不,catch 只是为了处理错误,你不应该在 catch 中发送 200,如果你不想让你的应用停止不要发送 500,你可以使用类似 throw new Error('The data was not load');
    【解决方案2】:

    对于这种情况

    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 块,因为响应状态取决于错误,而不是相反

    【讨论】:

      【解决方案3】:

      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:用于在对象表示中引入空格

      【讨论】:

      • 完美。我得到了它。假设我想发送一条特定的错误消息,例如。 “数据未加载”。最好的方法是什么?我应该在服务器端做吗?
      • 取决于您的用例。如果您不想向 API 的用户显示错误,您可以随时打印一个甜蜜的“哦!有东西坏了。我们正在努力!”信息。如果要向用户显示,则可以在两个地方都使用 stringify 。在测试时,我建议在服务器和 API 用户双方都显示错误。
      • 是的,数据没有在服务器端加载消息将是一个好主意。
      【解决方案4】:

      作为一名使用 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
      }
      

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

      【讨论】:

      • Tku 这么多。你的反应很有帮助。发送这样的消息res.status(500).send({error: 'I can only make tea' }),在客户端显示此消息的最佳方式是什么?如果我在 catch 块内执行类似 console.log(error) 的操作,则不会显示此消息。
      • 那是你决定如何显示它,每个公司以不同的方式这样做,例如,微软只是在 azure 上显示一个加载程序(该死的微软!),一些网站只会输出到日志,因为他们很懒惰,有些人会展示小吃店或吐司或一些带有信息的模式 - 取决于问题和您的前端文化。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-04
      • 2021-02-11
      • 2010-09-09
      • 1970-01-01
      • 2020-03-05
      • 1970-01-01
      相关资源
      最近更新 更多