“This is the 24th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Errors can be caught using try catch, thanks to the asynchronous programming model supported by the framework. When writing application code, exceptions can be caught directly with a try catch everywhere.

// app/service/test.js
try {
  const res = await this.ctx.curl('http://eggjs.com/api/echo', { dataType: 'json' });
  if(res.status ! = =200) throw new Error('response status is not 200');
  return res.data;
} catch (err) {
  this.logger.error(err);
  return {};
}
Copy the code

In normal code writing, all exceptions can be caught and handled in this way, but it is important to be aware of some of the problems caused by special writing. To use a less formal analogy, our code is all in an asynchronous call chain, and all asynchronous operations are connected with await strings, but as long as one part of the asynchronous call chain breaks, the exception is not caught.

// app/controller/home.js
class HomeController extends Controller {
  async buy () {
    const request = {};
    const config = await ctx.service.trade.buy(request);
    // After placing an order, a check is required without blocking the current request
    setImmediate(() = >{ ctx.service.trade.check(request); }); }}Copy the code

In this scenario, if a problem with the code in the service.trade.check method causes it to throw an exception, the framework will catch the error through a try catch on the outermost layer, but because the code in setImmediate “jumps out” of the asynchronous chain, Errors in it can’t be caught. So be careful when writing code like this.

Of course, the framework also takes this scenario into account by providing the ctx.runinBackground (scope) helper method, which wraps an asynchronous chain and all errors within this scope are caught uniformly.

class HomeController extends Controller {
  async buy () {
    const request = {};
    const config = await ctx.service.trade.buy(request);
    // After placing an order, a check is required without blocking the current request
    ctx.runInBackground(async() = > {// All exceptions are captured by Backgroud and an error log is printed
      awaitctx.service.trade.check(request); }); }}Copy the code

In order for exceptions to be traceable, it is important to ensure that all exceptions thrown are of the Error type, because only the Error type will carry stack information to locate the problem.

Framework layer unified exception section

Although the framework provides a unified exception handling mechanism by default (dev displays stack information), application development often needs to customize the response to exceptions, especially when doing some interface development. The framework’s onError plug-in supports custom configuration error handling that overrides the default error handling.

// config/config.default.js
module.exports = {
  onerror: {
    all(err, ctx) {
      // Define error handling for all response types here
      // Note that other error handling methods do not take effect after config.all is defined
      ctx.body = 'error';
      ctx.status = 500; ,}}};Copy the code

404

The framework does not treat the 404 status returned by the server as an exception, but the framework provides a default response when the response is 404 and no body is returned.

  • When a request is determined by the framework to require a JSON-formatted response, a JSON fragment is returned:
{ "message": "Not Found" }
Copy the code
  • When a request is determined by the framework to require an HTML response, an HTML is returned:
<h1>404 Not Found</h1>
Copy the code

The framework supports configuration to redirect a 404 response to a default HTML request to a specified page.

// config/config.default.js
module.exports = {
  notfound: {
    pageUrl: '/404.html',}};Copy the code

Customize the 404 response

In some scenarios, we need to customize the server 404 response. As with custom exception handling, we also need to add a middleware to handle 404 uniformly:

// app/middleware/notfound_handler.js
module.exports = () = > {
  return async function notFoundHandler(ctx, next) {
    await next();
    if (ctx.status === 404 && !ctx.body) {
      if (ctx.acceptJSON) {
        ctx.body = { error: 'Not Found' };
      } else {
        ctx.body = '<h1>Page Not Found</h1>'; }}}; };Copy the code

Introducing middleware into the configuration:

// config/config.default.js
module.exports = {
  middleware: [ 'notfoundHandler']};Copy the code