HomeAbout

Async in JS

What does Asynchronous mean in Javascript

When you have a long-running synchronous code (e.g. generate 10,000,0000 prime numbers), JS code will be stuck until this code completes because JS is single threaded.

Async allows a long-running operation to return immediately.

The thread will continue to the rest of the program, then resume when the long-running operation completes (resolves).

Promise

A Promise represents theĀ future result of an asynchronous operation.

.then()

Handles resolved or rejected value of a Promise.

Takes in two parameters:

  • callback functions for fulfilled Promise and rejected Promise
function api() { return new Promise((resolve, reject) => { // ... }) }

Using .then() can write asynchronous code in a way that resembles synchronous code which is easier to follow.

const promise1 = new Promise((resolve, reject) => { resolve("Success!"); }); promise1.then((value) => { console.log(value); // "Success!" });

Chaining

.then stores the callbacks within the Promise it is called on and immediately returns another Promise object, allowing you to chain calls to other Promise methods.

api() .then(function(result){ return api2(); }) .then(function(result2){ return api3(); }) .then(function(result3){ // do something with result3 }) .catch(function(error) { //handle any error });
  • catch is same as a try { ... } catch block structure.

If the return value within .then() is not a promise, it's implicitly wrapped in a Promise and then resolved.

const p2 = new Promise((resolve, reject) => { resolve(1); }); p2.then((value) => { console.log(value); // 1 return value + 1; }).then((value) => { // synchronous value works console.log(value); // 2 }); p2.then((value) => { console.log(value); // 1 });

Promise vs Callback

Promises are NOT Callbacks

Before Promise, Async JS codes relied on callback functions to be executed after a desired time.

  • Although both Promise and callbacks can be used to achieve the async, they are fundamentally different things.

Chaining multiple asynchronous operations after other in a row with callback resulted in the pyramid of doom.

doSomething(function (result) { doSomethingElse(result, function (newResult) { doThirdThing(newResult, function (finalResult) { console.log(`Got the final result: ${finalResult}`); }, failureCallback); }, failureCallback); }, failureCallback);

With promise, you break out of the pyramid shape

const promise1 = doSomething(); const promise2 = promise1.then(successCallback, failureCallback);

async

Syntactical sugar for Promise.

// Arrow Function // named arrow function expression const foo = async() => { // ... } // single arg // avoid const foo = async arr => { // do something with arr } // multiple args const foo = async(arr, callback) => { // use arr and callback } // Function Declaration async function foo() { // ... } // anonymous async in callback const foo = event.onCall(async() => { // ... })
async function fetchMovies() { const response = await fetch('/movies'); // waits until the request completes... console.log(response); } // example of useEffect in React useEffect(() => { const fetchData = async () => { // some code like fetch() }; await fetchData() .then( (res) => // ... ) .catch( (e) => console.error(e) );; }, [])

Async vs Promise

Main difference is in scope

In the below example, promise is kicked off right as they are defined

  • Whereas async/await will execute one Promise at a time
// Operation A & Operation B can run in parallel Promise.all([ returnsAPromise(opA), returnsAPromise(opB) ]) .then(res => { // waits info from both Operations A & B console.log("done") } ); // With Async // Operation A executes first, then Operation B const asyncFn = async () => { // Operation A runs first const resultA = await returnsAPromise(opA); // Operation B runs after Operation A completes const resultB = await returnsAPromise(opB); // Then, Operation C,D,E... runs console.log("done"); } asyncFn();

To parallel process async/await, we use it with Promise.all() and combine scope via destructuring:

const asyncFnParallel = async () => { // Operation A & Operation B can run in parallel const [resultA, resultB] = await Promise.all([ returnsAPromise(opA), returnsAPromise(opB) ]); // Operation C,D,E... runs after Operation A and Operation B console.log("done"); } asyncFnParallel();

Execution Behavior of Promise vs Async

Promises run automatically without being called

You don't "declare" Promises:

  • new Promise creates a Promise.
    • calls the executor function you pass it, synchronously, before new Promise returns.

If you want to define a Promise, but don't want to start it until specific point in time, you define it inside async function:

async function startPromise() { // ...other Promise can sit here too } let processPromise = startPromise();
AboutContact