DEV Community

hyunho98
hyunho98

Posted on

Fetch Requests, Promises, and Asynchronous Code

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:

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
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)