2
1
3
Cover image for Understanding Asynchronous JavaScript 👨‍💻

Understanding Asynchronous JavaScript 👨‍💻

Asynchronicity

Asynchronicity is the backbone of modern web development in JavaScript

JavaScript is single threaded (one command executing at a time) and has a synchronous execution model (each line is executed in order the code appears).

So what if we need to wait some time before we can execute certain bits of code? We need to wait on fresh data from an API/server request or for a timer to complete and then execute our code We have a conundrum - a tension between wanting to delay some code execution but not wanting to block the thread from any further code running while we wait.

Let’s see two examples: In what order will our console logs occur?

function printHello(){ console.log(“Hello”); } setTimeout(printHello,1000); console.log(“Me first!);

The output:

'Me first!' 'Hello'

function printHello(){ console.log(“Hello”); } setTimeout(printHello,0); console.log(“Me first!);

The output:

'Me first!' 'Hello'

To understand the above behavior, we need to introduce 3 new components of our platform

  • Web Browser APIs/Node background threads
  • Callback/Message queue
  • Event loop

Now we are interacting with a world outside of JavaScript:

We need a way of predictably understanding how this outside world will interact with our JavaScript execution model. What would happen here?

function printHello(){ console.log(“Hello”); } function blockFor1Sec(){ /*blocks in the JavaScript thread for 1 second*/ } setTimeout(printHello,0); blockFor1Sec() console.log(“Me first!);

Promises

Essentially, a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function.

Promises - the readability enhancer:

  • Special objects built into JavaScript that get returned immediately when we make a call to a web browser API/feature (e.g. fetch) that’s set up to return promises (not all are)
  • Promises act as a placeholder for the data we hope to get back from the web browser feature’s background work
  • We also attach the functionality we want to defer running until that background work is done (using the built in .then method) — Promise objects will automatically trigger that functionality to run
  • The value returned from the web browser feature’s work (e.g. the returned data from the server using fetch) will be that function’s input/argument

Using two-pronged ‘facade’ functions that both initiate background web browser work and return a placeholder object (promise) immediately in JavaScript

function display(data) { console.log(data) } const futureData = fetch('https://twitter.com/will/tweets/1') futureData.then(display); console.log('Me first!');

In the above code, the function display will be declared and its function text and name will be stored in the global memory. futureData will be uninitialized until fetch is executed (futureData will be the returned value of fetch ). fetch() is a two-pronged 'facade' function, it's a function masking a bunch of JS functionality and browser work. On one hand, it's sending an XMLHttpRequest to Twitter's API (browser work), on the other hand, it's returning us a Promise object (JS work).

We're hoping it will return the data from Twitter. Just like setTimeout kicks off Timer in the browser, fetch kicks off XHR (XMLHttpRequest) object. fetch will immediately return an object with a property on it called value, which is undefined (the data received from Twitter will be set to value). It also has a property called onFulfillment which is an empty array; we can store any functions we want to auto-trigger when the value gets updated to the data. This returned object will be set to FutureData. You might say that we can run FutureData.value, but the problem is that we don't know when the value will be updated (right now it's undefined). (On completion of the request in future, we will assign the received data to the value, which, like we said earlier, will trigger all the functions in onFulfillment.

The next line seems that it's calling display function. All .then() does is it takes its functions and stores it in onFulfillment array; the functions are triggered when the value is updated. So here, when we will assign the received data to the value, .then() will store the display function (its argument) ). Next, we run console.log('Me first!');. Now, the response data comes, the status property is set to resolved and the value is updated to hi. The display function will be triggered with value as its argument.

Discussion (8 comments)

avatar
avatar
test
Sep 22, 2022
test
avatar
test
Sep 22, 2022
test2
avatar
Jon Don
May 21, 2024
asfasfasf
avatar
Jon Don
May 21, 2024
asfasfsaf
avatar
Jon Don
May 21, 2024
asfasfsaf
avatar
Jon Don
May 21, 2024
asfsafsf
avatar
Khuslen UUJII
Jul 22, 2024
za
avatar
Khuslen UUJII
Jul 22, 2024
ada
avatar

Matthew Wiebe