learn-webapp-guideline icon indicating copy to clipboard operation
learn-webapp-guideline copied to clipboard

尽管使用了统一的错误处理机制,但是在第17个例子中,没有爆出想要的错误的提示

Open MyColourfulLife opened this issue 7 years ago • 2 comments

比如运行第17个案例, 在登录注册时故意输错 点击登录浏览器会报以下错误:

Failed to load resource: the server responded with a status of 500 (Internal Server Error)

而我们在处理api时,其实已经给出友好的错误的提示:比如用户不存在,密码有误等信息。而上面的错误不是我们想要的样子。

虽然使用了中间件errorHandel,但最终的错误处理是在app.js中处理的。 修改app.js 中错误处理的代码,比如新增自己对错误的处理,还是不行。甚至直接把render改为send都不奏效。

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
****新增代码开始****
  if (err.status === 500 && req.baseUrl.startsWith('/api')) {
    res.send(err);
    return;
  }
****新增代码结束****
  // render the error page
  res.status(err.status || 500);
****改动代码开始****
  // res.render('error');
  res.send(err);
****改动代码结束****
});

所以,该如何解决这个问题呢?

此外: 既然我们使用errorHandel去处理错误,为何不直接把res也传进来,遇到错误,直接返回响应?而不像案例中那样继续next将错误留给app中的处理错误的中间件处理。

MyColourfulLife avatar Nov 22 '17 16:11 MyColourfulLife

感谢老师提示。

使用errorHandel作为应用中间件app.use()

整个项目瞥了一眼👁好多新语法,总的来说看起来很复杂。我看了errorhandle那个中间件,还是有些启发的。

知道了res.stauts().format();这个format会根据请求的Accept来返回相应的数据格式。

比如Accept是application/json就会走json那个函数等。详细点需要看下format这个函数。

于是,仿照老师的代码改造了下案例中的errorHandel中间件(这里没区分生产环境还是开发环境)

var errorHandle = function (err, req, res, next) {
  const errorDetails = err.stack || err;

  res.status(err.status || 500).format({
    json() {
      const errorInfo = {
        details: err,
        error: err.toString(),
      };
      res.send(errorInfo);
    },

    html() {
      const message = `<pre>${errorDetails}</pre>`;
      res.send(`<h1>500 Internal server error</h1>\n${message}`);
    },

    default() {
      const message = errorDetails;
      res.send(`500 Internal server error:\n${message}`);
    }
  });

}

module.exports = errorHandle;

然后把这个当做应用中间件,替代express给出的默认错误处理中间件。

在路由中也不用引入了,直接next(err),整体看起来更方便了。

了解err.response

alert的错误提示,没有给出想要的信息。打印err也没看出还有啥。

调试时是可以看到响应的,响应里真真切切的放着需要的信息。

可以怎么拿过来呢?

axios的then并没有捕获response,感觉很奇怪。

原来err还有个response属性。。。这里面包含了所有的响应信息,比如像这样(google浏览器调试界面,使用postman会简单些):

config:{...}
data:{details: {…}, error: "Error: 找不到用户"}
headers:{…}
request:XMLHttpRequest {…}
status:500
statusText:"Internal Server Error"
__proto__:Object

因此根据响应,修改客户端代码,即可弹出想要的信息。

 alert(err.response.data.error);

MyColourfulLife avatar Nov 23 '17 09:11 MyColourfulLife

补充事例:https://github.com/xugy0926/community/blob/master/src/middlewares/errorHandler.js

xugy0926 avatar Nov 27 '17 05:11 xugy0926