187

Scenario: Consider the following is the part of code from a node web app.

app.get('/users/:id?', function(req, res, next){
    var id = req.params.id;
    if (id) {
        // do something
    } else {
        next(); //or return next();
    }
});

Issue: I am checking which one to go with just next() or return next(). Above sample code works exactly the same for both & did not show any difference in execution.

Question: Can some one put light on this, when to use next() and when to use return next() and some important difference?

Amol M Kulkarni
  • 21,143
  • 34
  • 120
  • 164

6 Answers6

336

As @Laurent Perrin's answer:

If you don't do it, you risk triggering the callback a second time later, which usually has devastating results

I give an example here if you write middleware like this:

app.use((req, res, next) => {
  console.log('This is a middleware')
  next()
  console.log('This is first-half middleware')
})

app.use((req, res, next) => {
  console.log('This is second middleware')
  next()
})

app.use((req, res, next) => {
  console.log('This is third middleware')
  next()
})

You will find out that the output in console is:

This is a middleware
This is second middleware
This is third middleware
This is first-half middleware

That is, it runs the code below next() after all middleware function finished.

However, if you use return next(), it will jump out the callback immediately and the code below return next() in the callback will be unreachable.

PJCHENder
  • 5,570
  • 3
  • 18
  • 35
  • 69
    As a beginner to `express` this answer made things clearer to me than the other answers. Thumbs up! – mandarin Dec 19 '17 at 13:44
  • 2
    Would a similar thing be true of `res.redirect('/')` vs. `return res.redirect('/')` in this type of situation? Maybe it's just better to always write `return` in front of `res` statements to avoid errors of setting headers after they were sent? – Adam D Sep 07 '18 at 06:45
  • 2
    Why should I write code after next()? Isn't it obvious that I do nothing after I finished my task in a middleware? @PJCHENder – Imran Pollob Jul 25 '19 at 06:17
  • 1
    @ImranPollob sometimes mistakes happens. When you write a lot of code, ifs/elses/etc. You may forget ```return next()` – Jone Polvora Jul 25 '19 at 16:45
  • 1
    @ImranPollob - There could very well be times where you want your code to *unwrap* (so to speak), and come back to a middleware that was executed earlier. The fact that it will only actually unwrap and reach code positioned after `next()`, if no other middleware's have `return`ed yet, could be exactly what you're looking to do. Special types of logging, caching, or analytics spring to mind as potential use cases, although this should really be used sparingly, as it would quickly become confusing if you're using this technique all over the place. – Jack_Hu May 04 '22 at 23:27
200

Some people always write return next() is to ensure that the execution stops after triggering the callback.

If you don't do it, you risk triggering the callback a second time later, which usually has devastating results. Your code is fine as it is, but I would rewrite it as:

app.get('/users/:id?', function(req, res, next){
    var id = req.params.id;

    if(!id)
        return next();

    // do something
});

It saves me an indentation level, and when I read the code again later, I'm sure there is no way next is called twice.

Laurent Perrin
  • 14,671
  • 5
  • 50
  • 49
  • 3
    Would a similar thing be true of `res.redirect('/')` vs. `return res.redirect('/')` in this type of situation? Maybe it's just better to always write return in front of res statements to avoid errors of setting headers after they were sent? – Adam D Sep 07 '18 at 06:46
  • @AdamD I would like to know that as well. – theprogrammer Sep 01 '20 at 23:01
  • @theprogrammer Yes, I think this answer applies the same way to things like `res.redirect` and it would be best practice to use it, unless you have some other server tasks you want to do after redirecting the user. – Adam D Sep 04 '20 at 01:47
53

next() is part of connect middleware. Callbacks for router flow doesn't care if you return anything from your functions, so return next() and next(); return; is basically the same.

In case you want to stop the flow of functions you can use next(err) like the following

app.get('/user/:id?', 
    function(req, res, next) { 
        console.log('function one');
        if ( !req.params.id ) 
            next('No ID'); // This will return error
        else   
            next(); // This will continue to function 2
    },
    function(req, res) { 
        console.log('function two'); 
    }
);

Pretty much next() is used for extending the middleware of your requests.

drinchev
  • 19,201
  • 4
  • 67
  • 93
  • 1
    Can we send parameter like: `next('No ID')` ? – Amol M Kulkarni May 29 '13 at 12:10
  • 9
    `next('No ID')` is actually sending an error, which will break the flow. – drinchev May 29 '13 at 12:15
  • Use next(null, "somevalue"); For tools like async.waterfall it will pass the value to the next function. For complex series of interactions that are data driven, I usually pass a context object between functions. That way I can create generic functions that can be shared across multiple end points and control flow via data in the context – Chad Wilson Oct 30 '15 at 00:12
  • 7
    "so return next() and next(); return; is basically the same." - just what I needed to read. thx @drinchev – Nick Pineda Feb 25 '16 at 01:25
  • 2
    I observe the opposite (when firing error): next(error) triggers next middleware, but continues to execute code; return next(error) just relegates execution to the next middleware. next(e) and return next(e) are NOT the same. – Nickolodeon Jul 25 '18 at 17:06
  • But than I admit that context here is a bit different. But still, if you anticipate (or generate error) several errors in async middleware, you should 'return next(e)' – Nickolodeon Jul 26 '18 at 08:39
  • Wrong about next(). It can't stop the flow of the function it's in. The next() function itself will return to the next line. – grantwparks Nov 27 '18 at 18:40
4

The difference between next() and return next() is very simple as another programming principle. Some lines of code are explain below:

    app.use((req, res, next) => {
       console.log('Calling first middleware');
       next();
       console.log('Calling after the next() function');
    });


    app.use((req, res, next) => {
       console.log('Calling second middleware');
       return next(); // It returns the function block immediately and call next() function so the return next(); and next(); return; are the same
       console.log('After calling return next()');
    });

Output is

Calling first middleware
Calling after the next() function
Calling second middleware

Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58
3
import express from "express"
  
const app = express()
// API for the testing of next() 
app.get(
  '/next', function (req,res,next) { 
    console.log('hi there ');
    next();
    console.log('you are still here');
  }
)
  
// API for the testing of return next() 
app.get(
  '/return-next', function (req,res,next) { 
    console.log('hi there');
    return next(); 
    console.log('you are still here');
  }
)
  
app.listen(5000,()=> {
  console.log("App is running on port 5000")
})

next() in /**next** route will call the middlewares and after the middlewares are executed it comes back to where it is called (same like a function call) and executes the rest of the codes

output:

hi there

you are still here

In /**return-next** route there is a return in front of next() which returns the controller

output:

hi there 

if you consider next() like a function call you could understand it properly

lejlun
  • 4,140
  • 2
  • 15
  • 31
0

Rony's example is quite good. However, I believe that the output is:

Calling first middleware
Calling second middleware
Calling after the next() function