Categories
Modern JavaScript

Best of Modern JavaScript — Async and Promises

Spread the love

Since 2015, JavaScript has improved immensely.

It’s much more pleasant to use it now than ever.

In this article, we’ll look at JavaScript async programming.

Sync and Async

The synchronous code always runs before the async code.

So if we have:

setTimeout(function() {
  console.log(2);
}, 0);
console.log(1);

Then we get:

1
2

The console log outside is synchronous, so it runs first.

The callback’s console log runs after the synchronous code, since it’s async.

The event loop may be blocked if we run something that’s synchronous since the whole app is managed by a single process.

Both the user interface and other computations are all in one thread.

So if one thing runs, then whatever comes after it can’t run until that thing is done.

For instance, if we have a synchronous sleep function, then that’ll pause the execution of the whole program.

If we have:

function sleep(ms) {
  const start = Date.now();
  while ((Date.now() - start) < ms);
}

console.log('start');
sleep(2000);
console.log('end');

Then we see 'start' logged first, then wait 2 seconds, then 'end' is logged.

The sleep function uses a while loop, so it’s synchronous.

This means it’ll hold up the whole program from running.

Avoiding Blocking

To avoid blocking the UI thread, we can use different kinds of async code like web workers, or setTimeout or Promises.

One example of async code is the Fetch API.

We can get data by making HTTP requests without blocking the whole thread.

For instance, we can write:

fetch('https://api.agify.io/?name=michael')
  .then(res => res.json())
  .then(res => {
    console.log(res);
  })

to use the fetch function to get the data.

It returns a promise so it’s async.

Then then callbacks are called only when the results are ready.

When it’s not the promise is paused until a result is obtained.

Asynchronous Results

Other examples, include Node.js async callbacks.

For example, the readFile method takes a callback that’s run asynchronously when the file is read.

We can write:

fs.readFile('foo.txt', {
    encoding: 'utf8'
  },
  function(error, text) {
    if (error) {
      // ...
    }
    console.log(text);
  });

Then we read file.txt from with readFile .

Callbacks

Callbacks are problematic because error handling is complicated.

We’ve to handle errors at each callback.

The signatures are also less elegant because there’s no separation of concerns between inputs and outputs.

Async functions use callback functions, which can’t return anything.

Composition is also more complicated.

Node style callbacks some problems.

We’ve to check for errors with if statements.

Reusing error handlers is harder.

And providing a default handler is also harder.

Promises

Promises are a pattern of async programming where a single result is returned asynchronously.

They’re better than callbacks since they can be chained.

Promises are returned by various functions and serve as the placeholder for the final result.

For instance, a promise chain may be written by writing:

asyncFunction(arg)
  .then(result => {
    console.log(result);
  });

We can have more than one then call if the then callback returns a promise.

For instance, we can write:

asyncFunction(arg)
  .then(result1 => {
    console.log(result1);
    return asyncFunction2(x, y);
  })
  .then(result2 => {
    console.log(result2);
  });

Conclusion

Promises are a better way to write async code in JavaScript.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *