Asynchronous JavaScript: A Comprehensive Guide

August 28, 2020
Written by
AJ Saulsberry
Opinions expressed by Twilio contributors are their own


Are you learning JavaScript and trying to understand asynchronous programming? Are you currently a JavaScript programmer who needs an overview of the asynchronous features of JavaScript? Or are you trying to decide which asynchronous technique best suits a programming task you’re trying to accomplish?

If you identify with any of these descriptions — or even if you’re just looking for a refresher on a specific asynchronous technique — the Asynchronous JavaScript series here on the Twilio blog can help. The series covers everything from callbacks to the async and await keywords; and it even includes RxJS Observables, a widely-used external library for handling asynchronous tasks.

Each of the posts includes complete source code for a runnable Node.js project demonstrating the technique covered in the post, and the posts are unified by a common case study so you can compare different approaches to the same task. The code for each post is also available on GitHub under an MIT license so you can download it and use it in your own projects.

Introducing the Asynchronous JavaScript programming tutorials

Here’s a summary of the posts in the series along with a link to each post.

Asynchronous JavaScript: Understanding Callbacks

If you’re new to JavaScript asynchronous programming, start with this post: it covers the JavaScript event loop, events, and callbacks, and other fundamental aspects of JavaScript that have a role in asynchronous programming the JavaScript way. In addition to code you can run to see these language features in action, there are also some nifty animations to help you get a handle on the event loop sequence of events.

Asynchronous JavaScript: Organizing Callbacks for Readability and Reusability

If you’ve been programming for any length of time you’ve likely had to refactor some code. In JavaScript, refactoring nested callbacks is likely to improve the readability of the code and make it easier to maintain and debug. This post builds on the case study introduced in the first post in the series to show you how you can improve the structure of callback code. It also points out aspects of callbacks that should be marked for additional refactoring.

Asynchronous JavaScript: Introduction to JavaScript Promises

Promises are the most powerful asynchronous capability that’s built into the language itself. They offer a number of advantages over callbacks and are a powerful and flexible approach to handling asynchronous tasks. They can be used to wrap callbacks and they’re used as the return type by many REST APIs. Promises are an essential part addition to your JavaScript toolkit. To guide you through the sequence of events that happen in Promise execution there are some nifty diagrams. There’s also a section on handling things when they don’t go the way you expect them to: Promise rejections and exceptions are important aspects of this language feature.

Asynchronous JavaScript: Advanced Promises with Node.js

This post builds on the information in the Introduction post by delving deeper into how Promises represent the state of an asynchronous action and how values returned by Promises can be manipulated. Individual Promises provide powerful functionality, and you can also use collections of Promises to perform actions based on the state of Promises in the collection. Promises can also be chained together to perform a series of actions that manipulate their values and change the path of program execution. You can see all these techniques in action and experiment with them using the code in this post.

Asynchronous JavaScript: Refactoring Callbacks to Promises in Node.js

Few programmers are lucky enough to always work on greenfield projects, and even your new code can sometimes benefit from refactoring as you move forward with development. One of the most effective ways to refactor older JavaScript code is to convert callbacks to Promises. Using the case study project for this series, this post provides a practice example of how to effectively refactor callbacks into Promises, including how to implement error handling with Promises.

Asynchronous JavaScript: Introducing ReactiveX and RxJS Observables

Reactive Extensions (ReactiveX) are one of the most widely-adopted sets of tools in programming today. ReactiveX libraries for JavaScript and other languages provide a way to operate on sequences of data as if they were events. RxJS is the ReactiveX implementation for JavaScript. Learning to use RxJS gives you a powerful toolkit for dealing with static or dynamic data streams like data emitted by a REST API.

This post explains RxJS Observables and how to use them with the observer and iterator patterns of functional programming. You’ll also learn about how Observables compare to Promises and how to handle errors in Observables.

Asynchronous JavaScript: Introducing async and await

Sometimes it doesn’t matter when your asynchronous tasks return values as long as they eventually do. (Or do not. There is no try. That’s handled by try…catch.)

But in a lot of cases a program needs to wait for the completion or failure of an asynchronous task before proceeding, either because it needs to know that the task was successful or not, or because it needs the data from the task to continue processing. This post explains the async and await keywords and demonstrates how to use them with a practical example. You’ll also learn about the potential performance pitfalls of injudicious use of await.

Asynchronous JavaScript: Using RxJS Observables with REST APIs in Node.js

Because ReactiveX programming enables you to react to data as it’s emitted from a source, rather than have to get the data from it, ReactiveX is a great fit for working with the REST APIs provided by web services. This post shows you how to use RxJS Observables with REST APIs using the practical case study that’s common across all the Asynchronous JavaScript posts. You’ll be able to see how to use RxJS operators to manipulate responses from an API, create a new Observable based on the data emitted by a previous Observable, combine Observables, and perform side-actions when Observables emit new data.

Asynchronous JavaScript: Selecting the Right Asynchronous JavaScript Tool

With all these asynchronous tools available to you, sometimes it can be tough choosing the most appropriate one for a specific task. Sometimes the best choice is to combine more than one, like using RxJS Observables with async and await. (How to do that is explained in the previous post.)

This post provides you with a decision tree for choosing the best asynchronous tool(s) for specific programming tasks. It’s presented as both flowchart and tabular form for different styles of learning. The post also includes some practical tips to help you use asynchronous techniques more effectively.

Additional resources

Twilio account – If you sign up for a free Twilio account using this link you’ll receive an additional $10 credit when you upgrade. It will come in handy when you do some of these tutorials.

Asynchronous JavaScript: Tools, Techniques, and Case Studies – Put your new knowledge to use with the tutorials listed in this collection.

If you’re looking for reference documentation on the topics covered in the posts mentioned here, check out the following canonical sources:

JavaScript | MDN – Part of the Mozilla Developer Network’s web docs, this is an essential source for JavaScript reference information and tutorials.

Draft ECMA-262 – Want to know what’s coming next in JavaScript? This is the official draft specification for the next version. Although called JavaScript, the language is officially ECMAScript.

RxJS Manual – Regardless of whether you know what it means to “think of RxJS as lodash for events” or not, this is the essential reference for Observables and related entities.

ReactiveX – See this site to better understand the concepts that RxJS implements for JavaScript.

Node.js Docs – Node.js provides a runtime environment for JavaScript so you can run JavaScript programs from your operating system’s console prompt. That’s pretty useful, so it’s a good idea to know something about it. If you want to be au currant, you might want to check out Deno, a new critter on the RTE landscape.

V8 – The JavaScript runtime environment used in most web browsers, including Chrome and Edge, is Google’s V8. It’s also used in Node.js and Deno, which pretty much makes it the foundation for running JavaScript programs.

TwilioQuest – Defeat the forces of legacy systems by completing JavaScript missions in this role-playing game inspired by the 16-bit golden age. Learning can be fun!