【问题标题】:How to return error to the client client without making node server crash?如何在不使节点服务器崩溃的情况下向客户端客户端返回错误?
【发布时间】:2021-04-24 15:54:03
【问题描述】:

我在节点服务器中有一条路由。当请求失败时,我需要发回一个可以在前端轻松捕获的错误。

基本上,我会这样做:

// server
app.get("/user/:id", async (req, res) => {
  try{
    const user = User.find(req.params.id)
    return res.status(200).json({user});
  }
  catch(err){
    throw new Error("error.user.route")
  }
});


// front
function fetchUser(id){
  return api.get("/user/" + id)
  .then(res=> res.data.user)
  .catch(err=> err.message)
  }
  
// somewhere in the dom
error && error.message

它工作正常,我可以将明确的错误消息传递给客户端,但是当服务器抛出错误时,它也会停止。在本地开发中调试非常好,但我不能在生产中出现这种行为。

我尝试简单地发送new Error("my message") 而不是投掷,但它没有落在catch 中。我可以发送res.json({error: "my message"}),但我想避免在我的前端处理条件错误。

有没有办法确保节点中的错误总是落在 api 调用的捕获而不导致服务器崩溃?

【问题讨论】:

    标签: node.js express error-handling


    【解决方案1】:

    最好将状态码发送到前端 https://restfulapi.net/http-status-codes/

     app.get("/user/:id", async (req, res) => {
      try{
         const user = User.find(req.params.id)
    
         if(!user) {
           res.status(404).json({error: "User not found"});
         }
        
         return res.status(200).json({user});
      }
      catch(err){
        return res.status(500).json({error: "my message"});
      }
    });
    

    并在 express https://expressjs.com/en/guide/error-handling.html#the-default-error-handler 中添加默认错误处理

    【讨论】:

    • 谢谢!通过添加正确的 http 错误代码,错误最终会出现在客户端 catch 中,而不会导致服务器崩溃。但是,我无法访问错误消息。我写了.catch(err=> console.log(err)),但我只收到一个内置的错误消息Error: Request failed with status code 400,而不是我的自定义消息。我尝试以两种方式创建错误:res.status(400).send(new Error('error.type.user'));res.status(400).json({error: 'error.type.user'});。它们都不起作用。
    • @DoneDeal0 你用什么库来从前端发送请求到后端?爱讯?如果是 axios,您的自定义消息将位于路径 err.response.data,其中 err 是捕获的错误对象。
    【解决方案2】:

    如上所述,您需要设置一个错误处理程序。我还建议在您的代码中添加以下帮助程序:

    export function fail(message, statusCode = 500) {
        const error = new Error(message);
        error.status = statusCode;
        throw error;
    }
    

    然后你可以像这样执行错误处理程序:

    server.use((error, req, res, next) => {
      const status = error.status || 500;
      const serverSide = status >= 500;
    
      // This is not a production way to do logging
      console.error(error);
    
      let message = error.message || getErrorForCode(status);
      if (serverSide && process.env.NODE_ENV === 'production') {
        message = 'Internal Server Error';
      }
    
      res.status(status).send(message);
    });
    

    那么你可以这样做:

    app.get("/user/:id", async (req, res, next) => {
      try{
        const user = await User.find(req.params.id);
        if (!user) fail('Not found', 404);
        res.json({user});
      }
      catch(err){
        next(err);
      }
    });
    
    

    注意:代码中不需要.status(200).json(..) 自动设置 200;你也错过了await :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多