Fetch Requests, Promises, and Asynchronous Code
Published: 2023-01-15 18:09:41

What happens when a fetch request is made in JavaScript? Most of it happens under the hood so it's easy to skip over when learning how to code in JS. However, learning how exactly a fetch request interacts with the machine and server is imperative to writing efficient code.

A quick summary of the order of operations when the machine runs a fetch request: 

1. Interpreter encounters the `fetch()` request
2. The machine creates a separate executable stack for the request
3. The machine continues running the program

_meanwhile..._

3a. The fetch request returns a **promise**
3b. The promise either returns resolved or rejected
3c. If the promise is resolved, runs any subsequent `then()` requests which also return promises which are then resolved/rejected

##Why is the `fetch()` request asynchronous code?##

Asynchronous code, put simply, is code that is set to run **not** in sync with the rest of the code. Fetch requests automatically fall under asynchronous code due to the nature of a promise. Promises run for an indefinite length of time so to make sure the program doesn't freeze at a certain point, the lines of code are run **while** the promise is waiting for resolution. And then whenever the promise is settled (when the promise is either resolved or rejected), the code goes back to the fetch request to either run (or not run) the rest of the fetch request or subsequent then statements.

##What exactly causes the promise to run for an indefinite amount of time?##

To understand why the machine decides to allocate a separate place in memory to run the fetch request, it's important to know what exactly a promise does. A promise has three possible states:

1. Resolved
2. Rejected
3. Pending

When a promise is either resolved or rejected, it is considered settled and the code within the fetch request is executed or skipped as a result. But even before that, the `fetch()` line makes a request to an external server, during which, the promise is placed in a pending state. While in this pending state, the local machine must wait for a response from the server machine to continue executing the program. The server machine isn't expected to respond instantly and any responses from the server are subject to latency. This is why a fetch request's runtime is considered indefinite and is executed independently of the rest of the program.

For example, here's an excerpt from my Flatiron phase 1 project, [Coffee Bean Database](https://github.com/hyunho98/coffee-bean-database):

```
fetch('http://localhost:3000/coffee_beans')
  .then((response) => response.json())
  .then((data) => {
    console.log(2) //CONSOLE LOG 2
    data.forEach((bean) => { 
      document.getElementById('tilecontainer')
      .append(createTile(bean))
        if (!locations.has(bean.location))
          createOption(bean.location)
    })
})
console.log(1) //CONSOLE LOG 1
```

Of the two console log lines, which do you supposed runs first? Surprisingly enough, the code logs `1` to the console before `2` even though `console.log(2)` occurs earlier in the code. Like in the example, this happens even when the server getting sent the request is running on a local machine. Depending on how long the server request takes, more lines of code may be run before the promise becomes settled. This must be kept in mind when creating or debugging asynchronous code as code that makes use of the data returned by a fetch request may encounter issues if the fetch request isn't settled by the time the compiler reaches it.