Day 25 (week 5) — The subtle difference between next() and return next()

Eric Abell
4 min readAug 19, 2017

--

Before I get to the difference between calling next() and return next(), I’d like summarize the day.

Our normal Friday Huddle consisted of some announcements, some information about career services and the plan moving forward, and a few presentations of projects that we had been working on. The thought is that by presenting our code, we get better at talking about code. I think this is a great thing to do, I only wish we had more time to do it. One of my suggestions moving forward is that we have more official code reviews on Github to practice using the same tools that we will most likely use in the workplace to review and comment on other people’s code.

I also had a nice one-on-one meeting about my resume and cover letters for the companies that I’m interested in applying to. Everyone is so organized and informed about the process moving forward. I can tell that there is deep experience and knowledge about how to find a job in software development. My hope is that I can take that information and use it in finding a job at the end of this training.

Alright, on to the difference between calling next() and return next(). I first noticed this several days ago when working through some example code in the nightly homework. We are using Express to define routes, and what I saw was something like this.

app.get('/post', function(req, res, next) {
Post.findById(1234).then(function(post, err){
if (err) {
return next(err);
}
if(!post) {
var notFound = new Error('Post not found!');
notFound.status = 404;
return next(notFound);
}
res.send(post);
});
});

Here we are handling a GET request on the path /post. In the callback, it would appear that we make some sort of call to Post.findById which probably is a query to database. Because this involves reaching out to a database and returning a Promise — which is clear from the use of .then — let’s look inside that function. Specifically, we see that if(err) is true, a call to return next(err) is made. Following that we have another if(!post) which again does a return next(notFound), and finally if we didn’t get any error and post has some data in it, we call res.send(post) which sends the result of the database query back to the browser.

In other examples, I would see something like this.

app.get('/foo',
function checkRegistration (req, res, next){
if(!req.user.registered){
// If user has not registered, skip to the next route.
// getRegistration will not be executed.
next('route')
}
}, function getRegistration (req, res, next) {
Registration.find(function (err, data){
if (err) return next(err)
res.json(data)
});
});

In this example, we just make a call to next('route'). So the natural question is what is the difference between using return or not?

It turns out, as I discovered today, that a call to next() inside a route does NOT immediately leave the function and proceed to the next route. In this case, the remainder of the route is evaluated and because next() was called, there is no need to resolve the request and we can simply move on to the next matching route handler.

Quick aside: remember that if you don’t resolve the request inside a route, Express won’t send anything back to the browser and you’ll be left hanging.

So, calling next() from inside a route simply tells Express that it should proceed with the remainder of the route and then move on to the next matching route.

Contrast this with calling return next() from within a route. The crucial difference is that when you call return next(), execution immediately leaves the function and proceeds to the next matching route. This is similar to the behavior of throwing an exception. Something has happened in our route and we want to skip any remaining code in the route and just jump to the next matching route.

My issue today was in trying to run a query to MongoDB where all my usernames and passwords are stored for my app. When I got to the POST request, which received the username and password that the client had just submitted, I need to run a query to see if there is a matching record in the database. This is an asynchronous call with a callback function. As far as Express is concerned, it continues executing my code while waiting for the result to come back from the database.

Turns out this is bad for me. Since Express is waiting on data to come back from the database, execution continues and I start seeing this error message.

Error: Can't set headers after they are sent.

This is Express continuing on when I really didn’t want it to. I had been using next() when I really wanted to be using return next().

Realizing this today was huge for me. It’s nice to complete the open loop from a few days ago in wondering what the difference in the two calls is. I can now go back and clean up my code for this project.

One last thing — the new weekly project was released today. We need to code up a webpage that allows you to play the classic game of Hangman. I’ll be tackling that this weekend! :-)

--

--