Home >Web Front-end >JS Tutorial >Detailed explanation of the usage of next function in express in nodejs
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: {} }); });
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)
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 !== 'boolean') { // 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); } }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 === 'route') { 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); } }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); } };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!