Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Express Basics Middleware The `next` function and a Closer Look at Middleware

Shane Unger
Shane Unger
9,401 Points

What did Andrew mean by the use of closures?

First off, I understand what a closure is, but I'm not sure the point he was trying to make at the very end of the video. Is he saying that any third-party function like cookieParser looks something like

const cookieParser = (() => { return (req, res, next) => { //some magic here with parsing cookies next(); } })();

?

2 Answers

Farid Wilhelm Zimmermann
Farid Wilhelm Zimmermann
16,753 Points

What Andrew wanted to explain was how the (req, res, next) parameters of the middleware functions, are passed down into predefined, 3rd party middleware methods such as cookieParser or bodyParser.

First lets have a look at how to include cookieParser into our express app:

        const cookieParser = require('cookie-parser');
        app.use(cookieParser()); 

As you can can see, we even though we pass cookieParser() as middleware, we don't explicity pass req, res, next parameters when invoking the method. So how do those arguments end up being used inside the cookieParser() method?

The answer is by the method being a closure.

function closure() {
  return function (req, res, next) {
    //Doing the actual modification of the request/response object and calling next() inside of here
    console.log(req); //logs 'Here we pass our request object'
    console.log(res); //logs 'Here we pass our response object'
    console.log(next);   //logs 'Here we pass the next() method'
  }
}

let cookieParser = closure();

cookieParser('Here we pass our request object', 'Here we pass our response object', 'Here we pass the next() method') 



module.exports.cookieParser = cookieParser; //export our module

In this oversimplified example, you can can see how a cookieParser() module could be developed, granted that there would be actually a lot of work to be done first, before this would parse anything!

So you might be asking yourself, why using a closure? While there are many possible reasons for this, one that everybody can directly see is that is cleans up the interface of our express application. cookieParser() just looks much cleaner than having to manually pass in the three parameters, while achieving the same result, having the req, res, next parameters downpassed automatically when being omitted in the app.use() method.

For further reading on why closures are being used so widely I refer to [https://softwareengineering.stackexchange.com/questions/203507/whats-so-useful-about-closures-in-js]

I hope that my explanation was understandable, closures are a really simple construct, whose use-cases for some weird reason tend to be really hard to grasp.

To piggy back on Farid's example, I tried an experiments to figure out what's going on behind the scenes with the arguments passed into the function's return function.

function closure(test1, test2, test3) {
  console.log(test1)
  console.log(test2)
  console.log(test3)
  return function (req, res, next) {
    //Doing the actual modification of the request/response object and calling next() inside of here
    console.log(req); //logs 'Here we pass our request object'
    console.log(res); //logs 'Here we pass our response object'
    console.log(next);   //logs 'Here we pass the next() method'
  }
}

let cookieParser = closure();

cookieParser('Here we pass our request object', 'Here we pass our response object', 'Here we pass the next() method') 

closure(5, 6, 7);
closure(1, 2, 3)("what prints out here","or here", "or even here?");
closure()("what prints out here","or here", "or even here?");
closure(1, 2, 3)();

module.exports.cookieParser = cookieParser; //export our module

Now the output...

undefined

undefined

undefined

Here we pass our request object

Here we pass our response object

Here we pass the next() method

5

6

7

1

2

3

what prints out here

or here

or even here?

undefined

undefined

undefined

what prints out here

or here

or even here?

1

2

3

undefined

undefined

undefined

Shane Unger
Shane Unger
9,401 Points
const cookieParser = (() => { 
  return (req, res, next) => { 
    //some magic here with parsing cookies 
    next(); 
  } 
})();