I'm reading example express source code for my education.
Initializing a simple express application looks like this:
const express = require('express')
const app = express()
app.listen(3000, () => {
console.log(`http://localhost:3000`)
})
I want to understand what app.listen
does in above code.
The source code of app.listen
is defined in express/lib/application.js, as following:
var app = exports = module.exports = {};
// ...
app.listen = function listen() {
var server = http.createServer(this); // <-- why `this` ??
return server.listen.apply(server, arguments);
};
Typically, http.createServer()
accepts a function as request handler. In this case, this
was passed in. But this
should refer to app
, it's not a function, right?
Later I found out app.handle was used as the request handler.
What is happening under the hood?
Thanks for your time!
this
is an enhanced instance of the app
prototype & it's being used as an options object for http.createServer
. To trace this sort of answer, we need to fully understand Node's CommonJS module implementation, the JavaScript prototypical inheritance system & JavaScript function scope.
The answer lays behind these lines: https://github.com/expressjs/express/blob/4.16.3/lib/application.js#L38 https://github.com/expressjs/express/blob/4.16.3/lib/express.js#L43
app
is a pointer to module.exports
, which represents how that module gets interfaced with from other Node modules. That module is only ever used internally by Express in lib/express, where it gets mixed in with another JavaScript prototype before being instantiated. Once an instance, each of the app
functions in lib/application share a this
that can be used to reference every property value & function on its prototype.
So...
Because http.createServer
accepts an options object as its 1st argument, ServerResponse
& IncomingMessage
will be used from app
/this
if available.
P.S. do not write code the way the Express team did it. You should never need to look through several modules to find the answer to a simple question like this. There are much simpler & team-friendly approaches to modularizing prototype mixins & default initializer options!