Writing Async Programs in JavaScript

Preface

There is no doubt that JavaScript, despite its history, has become to be one of the most popular programming languages today. JavaScript, due to its asynchronous nature, can present some challenges for those who are new to the language. In this article, we are going to write small async programs using promises and async/await. Using these examples, we are going to identify some simple patterns that you can use for your own programs.

If you are new to JavaScript, you may want to first check out my other article before reading this one.

All the code examples in this article are written for the Node environment. If you don’t have Node installed, you can see the Appendix 1 for instructions. Even though all the programs are written for Node, you can apply the same principles for scripts running in the browser. Also, all the code examples for this article are available on Gitlab.

Introduction

Whether or not people believe that JavaScript is a real programming language, the reality is that it’s not going to go anywhere anytime soon. If you are a web developer you might as well spend some time and learn its good and bad parts.

JavaScript is single-threaded and favors non-blocking asynchronous flows. If you are new to the language, it can become really frustrating when things don’t work the way you expect them to. Asynchronous programming demands more patience and a different kind of thinking that’s different from synchronous programming.

In the synchronous model everything happens in a sequence one at a time. Because of that it’s easier to reason about programs. But in the asynchronous model, operations can start or finish in any order at any point in time. Because of that simply relying on a sequence is not sufficient. Asynchronous programming demands more thought in terms of program flow and design.

In this article, we are going to explore a couple of short async programs. We are going to start with simple programs and work our way up to more complex ones. Below is an overview of the scripts that we are going to be writing:

  • A script that writes the content of a file to another file.
  • A script that writes the contents of multiple files to new files.
  • A script that parses and formats CSV files in a directory and outputs new CSV files to another folder.

Promises and Async/await

Let’s take a moment and quickly review the basics of promises and async/await.

Promises

  • A promise is an object that represents the result of an asynchronous operation.
  • A promise is either resolved with a “success” value or rejected with a “failure” value.
  • Generally speaking, resolved values are accessed with a callback’s argument to a then block. And the rejected values are access with a callback's argument to a catch block.
  • In modern JavaScript environments, you can access a promise constructor through the global object as Promise.
  • A promise can be created using the Promise constructor using the newkeyword. That is:
  • const p = new Promise((r, j) => {});
  • The r callback is used to resolve the promise with a value and the jcallback is used to reject the promise.
  • The Promise constructor has some useful static methods like all, race, resolve, and reject. The all method accepts an array of promises and will attempt to resolve all of them concurrently and return a promise that resolves to an array with the resolved values. The race methods takes an array of promises and resolves or rejects the first promise that finishes. The resolve method creates a promise and resolves it to the given value. The reject method creates a promise and rejects it with the given value.

Async/await

  • The purpose of async/await functions is to simplify the behavior of using promises synchronously and to perform some behavior on a group of Promises. From MDN
  • Just as Promises are similar to structured callbacks, async/await is similar to combining generators and promises. From MDN
  • A function can be marked as an asynchronous function with the asynckeyword. That is: async function hello() {} or const hello = async() => {};.
  • An async function always returns a promise. If a value is returned from an async function, it will be implicitly wrapped in a promise.
  • If there is an uncaught exception thrown inside an async function, the promise returned is rejected with the exception.
  • The await operator can be used inside an async function before statements that return a promise. In that case, the execution of the function is "paused" until the promise is resolved or rejected.
  • The await operator is only valid inside an async function.
You can read the rest of the article on medium.com