Why do we use next() function? - javascript

Do we use it only in middlewares or the functions with no routes? I have used it in my authentication file...
function ensureAuthenticated(req, res, next){
if(req.isAuthenticated()){
return next();
} else {
req.flash('error_msg' , 'Please login First...')
res.redirect('/users/login');
}
}

You execute it in order to execute the next middleware in the pipe. If you don't execute it manually, you're probably passing it on to a different module that executes it for you. Otherwise, if you don't execute next, you cut the "pipe" short i.e. yours is the last middleware that runs.
In your case it makes perfect sense to call next() when the user is authenticated. That passes the control to the next piece of middleware. It also makes sense not to call next() in the case that you've already established that the user is not authenticated, since in most cases you don't want the rest of the middleware in the "pipe" to execute.
So yes, next() is used by middleware, or modules intended to be called by middleware.
I hope that answers your question.

If you talking about Express framework here - next function is just a callback telling that this particular middleware handler should execute next operation in Express middleware chain.
If you define any handler with signature someHandler(req, res, next) and register it with app.use, it will become a part of that chain. Essentially it just a special callback function - disregarding the purpose of the function itself - route controller, authentication, body parser, etc.

Related

Question about the next() function in expressjs

I'm having trouble wrapping my head around the concept of the next() function in express.js. I guess my first question would be is next() an express.js only function? My second question would be, in the example below what does next do? After the console function, it goes to the next function that is called after? I'm so confused.
var cb0 = function (req, res, next) {
console.log('CB0');
next();
}
With Express (and other similar systems), each request passes through a series of middleware functions (like your cb0). Each of those has a chance to do something with the request.
Since the thing a middleware function does may be asynchronous (for instance, reading a file, querying a database, etc.), Express can't just directly call the next bit of middleware after calling the previous one. So instead, it passes the middleware function a function, next, which that middleware uses to say "I'm done, run the next step." (In the Express version, you can also pass an argument to next, as Aikon Mogwai points out: If you pass it an Error, it triggers error handling for the route. If you pass it "route", it jumps to the next router, etc.).
So the concept of a next function isn't specific to Express, but the specific use in that example is.
Here's a much simplified example not using Express, but demonstrating the sort of thing it does with middleware functions when handling a request:
const app = {
middleware: [],
use(callback) {
this.middleware.push(callback);
}
};
app.use((req, res, next) => {
console.log("First handler synchronous part");
setTimeout(() => {
console.log("First handler async part finished");
next();
}, 800);
});
app.use((req, res, next) => {
console.log("Second handler is entirely synchronous");
next();
});
app.use((req, res, next) => {
console.log("Third handler synchronous part");
setTimeout(() => {
console.log("Third handler async part finished");
next();
}, 800);
});
// Code handling an incoming request
function handleRequest(req, app) {
// Copy the handlers
const middleware = app.middleware.slice();
// Create a "response"
const res = {};
// Call the handlers
let index = 0;
next();
function next() {
if (index < middleware.length) {
// Call the handler, have it call `next` when it's done
middleware[index++](req, res, next);
} else {
console.log("Request completed");
}
}
}
handleRequest({}, app);
It's probably worth mentioning that this manual-style of asynchronous middleware handling has been replaced with promises in Koa.js, which is a new(er) framework from the same people who did Express.js. With Koa, you make your callbacks async functions, and Koa's internals wait for the promise the async function returns to settle and then acts on the result of it setting (e.g., rejection or fulfillment, the value it fulfills with, etc.).
Next is used to pass control to the next middleware function. If not the request will be left hanging or open. Calling this function invokes the next middleware function in the app. The next() function is not a part of the Node.js or Express API but is the third argument that is passed to the middleware function.
The next() function requests the next middleware function in the application. The next() function is not a part of the Node.js or Express API, but it is the third case/argument which is passing to the middleware function. The next() function could be named anything, but by convention, it is always named "next". To avoid confusion, always use this convention.
For more info, you can visit the official tutorial of express
var express = require('express')
var app = express()
var CB0 = function (req, res, next) {
console.log('CB0')
next()
}
app.use(CB0)
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
Each and Every time app receives a request and prints the message "CB0" console in terminal window.
The middleware functions that are loaded first are also executed first.
The middleware function CB0 simply prints a message, then passes on the request to the next middleware function in the stack by calling the next() function.

How does node.js next() middleware function work without arguments?

Middleware functions have a signature function (req, res, next), but in Express the next() call does not contain arguments. How is this so? See the following example from the
sample documentation
var express = require('express')
var app = express()
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
app.use(myLogger)
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
It certainly could be the case that a wrapping function is created that under-the-hood binds the arguments, allowing for a call with no additional parameters, but the documentation seems to indicate that the next parameter is called as-is, which does not make sense.
The docs describe the third argument, conventionally named next, as
Callback argument to the middleware function, called "next" by convention.
You can think of it similar to the conventional node.js callback-style argument provided to most async functions (without promises). When your middleware function is done doing its sync or async work, it should call next to indicate to the express router that it is done executing. This argument could be called done or callback, as we often see in other node.js libraries and examples, but is called next to provide a hint to the developer that the middleware chain will continue execution (other middleware may be called after this one).

Why don't I need to call next in a Sails.js controller function even if it has an (asynchronous?) database query in its body?

Example controller function:
getArticles: function(req, res) {
Articles.find({}).exec(function(err, articles) {
res.json(articles) // I guess this part is asynchronous
// next() here?
})
}
I am used to call next() at the end of an asynchronously executed block of code. That seems to be different in Sails.js. Can somebody explain this to me?
Because res.json() in this instance is the last thing you're asking the server to do. There is no next now.
The next() convention in this case is due to the fact that sails runs on top of express.js. Next() is the pattern in how express runs through its list of middleware. That is why you would use next() in your policies and such because they are middlewhere. res.json() however is at the end of the chain, so their is no need to call next().
If you're still confused, google express middleware next()
To use return? This example below shows why you would want to use return despite it not being needed. By using return we ensure that res.json('otherStuff') does not execute.
getArticles: function(req, res) {
Articles.find({}).exec(function(err, articles) {
if(true) return res.json(articles)
res.json('otherStuff')
})
}

app.get() third parameter in Node.js with Express

I am working through an excellent tutorial on using the Node.js package Passport (link) for user authentication, and I ran into a piece of code that I really don't understand:
app.get('/profile', isLoggedIn, function(req, res) {
res.render('profile.ejs', {
user : req.user // get the user out of session and pass to template
});
});
My question is with the isLoggedIn parameter. I looked at the official site, and did some google searches, but nowhere does it say that you can pass three parameters into app.get. I've only ever seen two. What is this third (optional, I assume) parameter?
I'm not asking about the isLoggedIn itself, but rather, about the fact that it's a third parameter I've never seen passed into app.get() before.
It's called middleware, and it's called before the third parameter (the callback).
Middleware functions examples: access checks, check to see if user is logged in before passing resources, and such.
It's in the express documentation: http://expressjs.com/en/5x/api.html#app.get
The syntax is:
app.get(path, callback [, callback ...])
i.e.
app.get(path, ...callback)
The syntax includes taking in a path as the first parameter, followed by as many middleware (having access to the request and response) callback functions as you desire. It's not limited to one. They are asynchronous and chained together by calling the next() parameter.
function callbackOne(req, res, next) {
//some code
next();
}
function callbackTwo(req, res, next) {
//some code
res.render();
}
app.get(path, callbackOne, callbackTwo)
So, in your case, the isLoggedIn parameter is simply just another middleware function that eventually calls next() if the user is logged in to bring execution to the third parameter.

How does next() work in Node.js?

I recently read a blog in Nodejitsu and I am wondering how this piece of code works.
var fs = require('fs'),
http = require('http'),
httpProxy = require('../lib/node-http-proxy');
module.exports = function (logging) {
// Code here is run when the middleware is initially loaded.
var logFile = fs.createWriteStream('./requests.log');
return function (request, response, next) {
// Code here is run on each request.
if (logging) {
logFile.write(JSON.stringify(request.headers, true, 2));
}
next();
}
}
And the explanation given for this piece of code is:
This middleware is for very simple logging - it will write the headers of each request to a log file.
the above module exported can be used as,
httpProxy.createServer(
require('./example-middleware')(true),
8000, 'localhost'
).listen(9000)
How is the code in the above method with next() invoked in every request? The usage is pretty simple: require the above module and it gets invoked every time.
I'll simplify the actual process but the gist of it:
When a request comes in, node passes the request and response object to the first middleware in the middleware stack. If that middleware sends a response or closes the connection in any way, then subsequent middleware are not called. Otherwise, that middleware has to tell node it's finished doing it's job to keep on moving through the middleware stack, so you call next() within your middleware to tell it to continue processing middleware.
Okay, so this is a pretty common thing. What this module contains is a single function, specified by this line, where we set module.exports to a function, module.exports = function (logging) {. The function returned by the module (and therefore returned by require()) returns another function, which is the middleware for the HTTP proxy (this middleware allows you to transforms the request). This middleware function gets called for every HTTP request made to the server. Quickredfox's answer provides a fairly good explanation of middlewares.
So the require('./example-middleware')(true) actually calls the function assigned to module.exports, but does not call the function inside that, which is returned immediately and passed as a middleware into the httpProxy.createServer function. This is a good way to set up some options for your middleware using closures. If you have any more questions, feel free to comment. :D

Categories

Resources