Home > Web Front-end > JS Tutorial > body text

Detailed explanation of the usage of next function in express in nodejs

巴扎黑
Release: 2017-09-09 09:54:25
Original
2259 people have browsed it

This article mainly introduces nodejs’s understanding of the next function in express, which has certain reference value. Interested friends can refer to it

Recently, the company is using node to separate the front and back ends. The web framework used is express, so I have an in-depth understanding of the express framework. I wrote an article about express routing some time ago, but it seems that a very important content is missing in that article, which is the next of express, so today Let’s talk about express’s next separately.

Regarding next, we will mainly explain it from three points:

  • What is the role of next?

  • When should we use next?

  • #What is the internal implementation mechanism of next?

The role of Next

When we define the express middleware function, we will define the third parameter as next, and this next is our Today’s protagonist, the next function is mainly responsible for handing control to the next middleware. If the current middleware does not terminate the request and next is not called, then the request will be suspended and the middleware defined later will not be executed. Opportunity.

When to use Next

We already know from the above description that the next function is mainly used to ensure that all registered middleware are executed one by one, then We should call the next function in all middleware, but there is a special case. If the middleware we define terminates this request, then the next function should not be called again, otherwise problems may occur. Let's look at this section. Code


app.get('/a', function(req, res, next) {
  res.send('sucess');
  next();
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
 console.log(404);
 var err = new Error('Not Found');
 err.status = 404;
 next(err);
});

app.use(function(err, req, res, next) {
 res.status(err.status || 500);
 res.render('error', {
  message: err.message,
  error: {}
 });
});
Copy after login

sends request "/a", the console prints the log as follows:


404
GET /a 500 6.837 ms - -
Error: Can't set headers after they are sent.
  at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:345:11)
Copy after login

Why does the code throw The exception is because we called the next function after res.send. Although our request has been terminated, the subsequent 404 middleware will still be executed, and the subsequent middleware attempts to add attributes to the headers of res. value, so the above exception will be thrown.

You may have a question after reading this. If I don't call the next function after res.send, will the 404 middleware defined later never be executed? Now we delete the next function call after res.send and send the request "/xxx", we will find that the 404 middleware is executed, (ㄒoㄒ), isn't this contradictory to what we said before, our customization The middleware does not call next, but the middleware defined later is still executed. Why is this? It seems that we can only ask for help from the source code~~~

Next’s internal mechanism


##

function next(err) {
  ... //此处源码省略
  // find next matching layer
  var layer;
  var match;
  var route;

  while (match !== true && idx < stack.length) {
   layer = stack[idx++];
   match = matchLayer(layer, path);
   route = layer.route;

   if (typeof match !== &#39;boolean&#39;) {
    // hold on to layerError
    layerError = layerError || match;
   }

   if (match !== true) {
    continue;
   }
   ... //此处源码省略
  }
 ... //此处源码省略
  // this should be done for the layer
  if (err) {
    layer.handle_error(err, req, res, next);
  } else {
   layer.handle_request(req, res, next);
  }
 }
Copy after login

The above is the source code of next in express. The code has been shortened to make it easier to illustrate the problem. From the source code above, we can find that there is a while loop inside the next function. Each loop will take out a layer from the stack. This layer contains routing and middleware information, and then the layer will be used to match the requested path. If the match is successful, layer.handle_request will be executed and the middleware function will be called. But if the match fails, the next layer (middleware) will be looped.

Now we can explain the problem raised above, why the next function is not called in our custom middleware, but the subsequent 404 middleware will still be executed because we requested "/xxx" The "/a" routing middleware we registered cannot be matched, so the while loop will continue to execute. The matching 404 middleware is successful, so the 404 middleware will be executed.

Note: For middleware registered with app.use, if the path parameter is empty, it defaults to "/", and middleware with a path of "/" matches all requests by default.

One thing needs to be pointed out in particular. In fact, when we define routing middleware, the third parameter next of the function is not the same next as the third parameter next of the function when we define non-routing middleware. What you see above is the next of non-routing middleware, and the next function of routing middleware is like this


function next(err) {
  if (err && err === &#39;route&#39;) {
   return done();
  }

  var layer = stack[idx++];
  if (!layer) {
   return done(err);
  }

  if (layer.method && layer.method !== method) {
   return next(err);
  }

  if (err) {
   layer.handle_error(err, req, res, next);
  } else {
   layer.handle_request(req, res, next);
  }
 }
Copy after login

This next is much simpler than the one above, and it is responsible for Transfer of control rights to multiple middlewares of the same route, and it will receive a parameter "route". If next("route") is called, it will skip other middlewares of the current route and directly transfer control rights to Next route.

Finally, it is necessary to talk about next(err) and how next(err) transfers control to the error handling middleware. From the previous code, we know that when next(err) is called, express layer.handle_error will be called internally, so let's take a look at its source code


Layer.prototype.handle_error = function handle_error(error, req, res, next) {
 var fn = this.handle;

 if (fn.length !== 4) {
  // not a standard error handler
  return next(error);
 }

 try {
  fn(error, req, res, next);
 } catch (err) {
  next(err);
 }
};
Copy after login
The fn in the code is the middleware function, and express will judge the number of parameters of fn , if the number of parameters is not equal to 4, it is considered not to be an error handling middleware, and then continue to call next(err), which will enter the next middleware function and continue to judge the number of parameters, in this way until a certain middleware If the number of parameters of the function is 4, it is considered that the error handling middleware is found, and then the middleware function is executed.

The above is the detailed content of Detailed explanation of the usage of next function in express in nodejs. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template