How do you access values passed to next() functions in Node - javascript

I'm using Node with Express.js to write a back-end for a project I'm working on.
next() functions are used in middleware to move to the next piece in the middleware chain, and finally onto the app.VERB() function. Where and how (further down the line) do I access this variable?
Example code:
app.use(function (req, res, next) {
User.findOne({
'email': emailValue
}, function (err, foundUser) {
if (err) return next(err);
// Else do something
}
});
});
What has access to the err value passed to next()?

When you pass an error parameter into next, Express invokes whatever error middleware handler you've installed. The error middleware function has four arguments, so you'd install your own handler as:
app.use(function(err, req, res, next) {
// handle the err from a previous middleware's next(err) call
});
You'd typically add this at the end of your middleware chain so that it handles all other middlewares' errors.
See here for the Express documentation on this.

Related

What is the first argument of next() in express js?

It seems you can pass an argument to next(), usually an error?
How is this used? How do I access that error?
eg:
router.get('/my-url', function(req, res, next) {
next(new Error('my error');
});
If you pass an error to next(), if will forward it to the error handler.
An error handler is a middleware defined with 4 inputs, where first input is an error.
So, you need to define an error handler in order to catch the error that is passed with next():
// Error handler
app.use((error, req, res, next) =>
console.log('ERROR:', error)
);

How Expressjs decides which error handler to call. if we have multiple error handles

I am just curious to know that how express decides which error handler to call (next(err)), when we have multiple error handlers.
If you have multiple errorhandlers, they will be called in the order you put them in your .use statements. Every errorhandler has to do next(err) though in order to pass the error on.
Taken from expressjs documentation:
app.use(logErrors)
app.use(clientErrorHandler)
app.use(errorHandler)
As an example from the documentation:
function errorHandler (err, req, res, next) {
if (res.headersSent) {
return next(err)
}
res.status(500)
res.render('error', { error: err })
}
So an error is beeing passed from handler to handler with the next(err) statement. And within that handler you decide what to do. You could for example check for a specific error and only act on that specific error.
expressjs documentation for errorhandling

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.

Javascript es6 - is it reassigning or a parameter?

Can someone please explain what's happening here? I know these are middleware for express, I'm looking at the syntax.
I understand the es6 syntax for mustBeLoggedIn but I'm not sure what const forbidden = message => (req, res, next) => { is doing. Is message another parameter that comes before req, res, next? If so, why isn't it in the parenthesis? I originally thought this was just assigning another variable name to the function. So I could call it either forbidden() or message(), no? But looking at how it's being used it looks more like a parameter...
Another interesting thing I noticed is that the middleware forbidden is being invoked in the get request and mustBeLoggedIn is only being passed and not invoked. Why?
const mustBeLoggedIn = (req, res, next) => {
if (!req.user) {
return res.status(401).send('You must be logged in')
}
next()
}
const forbidden = message => (req, res, next) => {
res.status(403).send(message)
}
module.exports = require('express').Router()
.get('/', forbidden('only admins can list users'), (req, res, next) =>
User.findAll()
.then(users => res.json(users))
.catch(next))
.post('/', (req, res, next) =>
User.create(req.body)
.then(user => res.status(201).json(user))
.catch(next))
.get('/:id', mustBeLoggedIn, (req, res, next) =>
User.findById(req.params.id)
.then(user => res.json(user))
.catch(next))
I dislike this use of the ES6 syntax as it obscures the meaning of the code only in the interest of brevity. The best code is not always the shortest possible way to write it. Give people tools and they will sometimes use them inappropriately.
forbidden() is a function that takes one argument message that returns a middleware handler that uses that one argument. So, it's a way of making a customized middleware handler that has a parameter pre-built-in. When you call forbidden(msg), it returns a middleware handler function which you can then use as middleware.
The ES5 way of writing this (ignoring for a moment the difference in this which would be different, but is not used here) would look like this:
const forbidden = function(message) {
return function(req, res, next) {
res.status(403).send(message);
}
}
So, when you call forbidden(someMsg), you get back a function that can be used as middleware.
If so, why isn't it in the parenthesis?
With the ES6 arrow syntax, a single argument does not have to be in parentheses. Only multiple arguments require parentheses.
Another interesting thing I noticed is that the middleware forbidden is being invoked in the get request
This is because invoking it returns the actual middleware function so you have to execute to get the return value which is then passed as the middleware.
and mustBeLoggedIn is only being passed and not invoked. Why?
Because it's already a middleware function, so you just want to pass a reference to it, not invoke it yet.
FYI, this route:
.get('/', forbidden('only admins can list users'), (req, res, next) =>
User.findAll()
.then(users => res.json(users))
.catch(next))
does not make sense to me based on the code you've shown because forbidden() will return a middleware that will ALWAYS return a 403 response and will not allow the next handler to get called. This would only make sense to me if forbidden() had logic in it to check if the current user is actually an admin or not (which you don't show).

Undefined Argument when using Callback function for express route

Currently, I am using many routes in Express. Some of the routes can be quite lengthy. A common route look like the following:
router.get('/api/comments', function(req, res, next){
Comment.find({"user": req.payload._id}).exec(function(err,comments){
if(err){return next(err); }
res.json(comments);
})
}
This works fine. But I am calling routes multiple times and it can be quite lengthy. So I am trying to create a callback function which can be invoked by the various routes. E.g.
var testFunction = function(req, res, next){
Comment.find({"user": req.payload._id}).exec(function(err,comments){
if(err){return next(err); }
res.json(comments);
})
}
router.get('/api/comments', testFunction(req,res,next));
However, I will always get a "req is not defined" error on the last line. Just wondering what I am doing wrong here?
router takes a function as argument not the result of executing that function.
router.get('/api/comments', testFunction); will work.
Try doing router.get('/api/comments', testFunction); instead of router.get('/api/comments', function(req, res, next)

Categories

Resources