Home > Enterprise >  shouldn't it generate infinite looping?
shouldn't it generate infinite looping?

Time:10-10

according to this website:

"https://medium.com/man-moon/express-js-under-the-hood-6452c897b316"

this snippet of code refers to what const app = express() is executed:

module.exports = function createApplication() {
    var app = function(req, res, next) {
        app.handle(req, res, next);
    };
    mixin(app, EventEmitter.prototype, false);
    mixin(app, proto, false);
    app.request = { __proto__: req, app: app };
    app.response = { __proto__: res, app: app };
    app.init();
    return app;
}

"

how the following is possible:

"var app = function(req, res, next) {
        app.handle(req, res, next);
    };"

we have app receving the function which within its scope there is a reference to app as well shouldn't that genereta an infinite looping?? the way I see app is pointing to sabe reference right?

CodePudding user response:

It is possible and works if you also define app.handle, for example:

var app = function(a) {
  app.handle(a);
};
app.handle = console.log;
app(1);

app is a function and app.handle is another function. The console displays it as

[Function: app] { handle: [Function: log] }

When you run this code, the argument 1 is logged to the console, because that's what app.handle does.

CodePudding user response:

There is no infinite loop here. Let's just dissect what each line of this does. Here's the code with line numbers added:

1 module.exports = function createApplication() {
2    var app = function(req, res, next) {
3        app.handle(req, res, next);
4    };
5    mixin(app, EventEmitter.prototype, false);
6    mixin(app, proto, false);
7    app.request = { __proto__: req, app: app };
8    app.response = { __proto__: res, app: app };
9    app.init();
10   return app;

Line 1 creates the function that will be used in const app = express().

Line 2 defines a local function named app. Inside the body of that function is a call to app.handle(). More on that later.

Lines 5 and 6 add a bunch of methods from other classes to the app object (allowing it to be a combination of methods from other classes known as a "mixin").

Lines 7 and 8 define parts of a default implementation for the req and res objects that will be used in handling requests. This is kind of used like a "prototype", though it isn't a classic system prototype.

Line 9 calls the Express object initialization code that further initializes the object. You can see that code here and it is what you would normally find in a constructor.

app.init = function init() {
  this.cache = {};
  this.engines = {};
  this.settings = {};

  this.defaultConfiguration();
};

Line 10 returns this new object that was just created.

So, in understanding what is actually executing here, you can see that the call to app.handle() is not actually executed when createApplication() is called. Instead, it's executed some time later when app(req, res, next) gets called. And, app.handle() is one of those methods that was added to the app object in this line mixin(app, proto, false);.

So, when createApplication() is called, it just creates the app variable, assigns a bunch of things to it as properties, does some other initialization and then returns that new function object. It does not call that new function object at that time and thus app.handle(...) is not executed when createApplication() is called.

Sometime later when Express is processing a request, app(req, res, next) will get called and that will then cause it to call app.handle(req, res, next). But, that doesn't create any sort of loop.

The code for app.handle() is where Express routing (to match a pre-defined route with the current incoming request) starts and is here.

  • Related