Why do I need to write request method handlers before app.listen()?


#1

Question

Why do I need to write request method handlers before app.listen()?

Answer

Having all the handlers before the app.listen() might seem counterintuitive for two reasons:

  • as we know, JavaScript reads a file almost the same way we read book pages in most languages, that is from up to down, left to right, and so app.listen() does not exist yet when we are declaring an app.get() method handler and therefore when we get to app.listen() we had already processed the code before.

  • app.listen() opens the server connection at the end, but there are no request handlers after to catch any server requests.

Those seem like compelling points but if we take a closer look at them, there are some holes in the reasoning, for example, yes, JavaScript reads all the code of the file from the top to the bottom, but if we have variables and methods/functions declared it goes to local memory to run when it is called, the same way with any javascript file, ie:

if we had a file:

let counter = 0; //create a variable counter
let counterButton = document.getElementById('count'); //select the button that will have to count

const increaseCounter = () => counter++; //create the function that counts

if(counterButton){ //check if the button exists (not returning undefined which is a falsy value)
  counterButton.addEventListener('click', increaseCounter); //if so we give it an event listener of a click, so whenever it happens the function will be called.
} else {
  let button = createElement('button'); //otherwise we will create the button
  button.setAttribute('id', 'count');
  button.addEventListener('click', increaseCounter); 
  document.getElementById('main').appendChild(button); //and added to an element we know is already there no matter what.
}

In that example we can see that when it runs, it clearly will not call the function increaseCounter, and we know that the if statement will run it’s code because it is not a function or a method or a variable, it is a conditional. Yet inside the increaseCounter function will still not be run, the element and document methods will but their tasks are to create and assign.

Create and assign is sort of what app.methods do, they are like event listeners for a server so when we write:

app.get('/route', (req,res,next) => {...});

we are setting up a get request listener on the route /route that when triggered it will call the arrow function we passed to it.

Now to the second point, why not declare all of it after app.listen() is called since they are all like event listeners for the server? A way to answer that is to think about app not just like a series of methods, but also an object that is being put together or even simpler, like a building.
Each request method is a floor, we might have scaffolds and construction elevators around it while we build, but once it is almost finished we have the structure to set up the elevator that people will use to access those floors, so at the end, when everything has been built and structured we will activate the elevator that will serve every request floor in the building.

-------------------------
|    |         |          |
-------------------------
|    |         |          |
-------------------------
|    |         |          |
-------------------------
|    |         |          |
-------------------------
|    |         |          |
-------------------------
|    |         | app.get()|
-------------------------
|    |.listen()|          |
------------------------------------------------
------------------------------------------------

The same way, app is structuring a service system for the server when we create our request method handlers, we want this functionality to exist in the “map” of our server before we open the connections to each route, app.listen() is the last piece of our puzzle, it opens the server to receive requests and direct them to the already existing route handlers.

As a last thought, It is possible to write a handler after app.listen(), it is not common because of the structural principles of express, but then again it is not written in stone, so all that I mentioned is based on a common guideline for express structure, yet express itself is very flexible and many teams might do things a little different.


FAQ: Code Challenges - Code Challenge