Course Description
Learning how to build and manage asynchronous programs is perhaps the most important part of becoming an effective JavaScript programmer. Unlike most programming languages, JavaScript is single-threaded. As a result, JavaScript programs must use async APIs to stay responsive to user input while performing long-running tasks like server requests and animations. You can't get very far in a JavaScript program without running across an asynchronous API. It is possible to build most asynchronous programs using a handful of simple functions. We will learn why most JavaScript developers approach asynchronous programming the wrong way, and how to avoid these common mistakes. By the end of these lessons you will know the tools, concepts, and libraries required to be an asynchronous programming ninja!
This course and others like it are available as part of our Frontend Masters video subscription.
Learn Straight from the Experts Who Shape the Modern Web
- 200+ In-depth courses
- 18 Learning Paths
- Industry Leading Experts
- Live Interactive Workshops
Table of Contents
Building Blocks
- Jafar Husain begins his course on Async Programming in JavaScript with a little background about himself and then talks about some of the complexities that arise with asynchronous programming. In this course, he will be demonstrating how to write complex async programs using just a few flexible functions.
- Before diving into asynchronous programming, Jafar wants to spend some time going through an overview of some of the JavaScript functions he will be using. He covers ES6 arrow functions, forEach, map, filter, and concatAll.
- Jafar demonstrates how to use the functions he introduced in the previous section to create useful collections from a data source. He then applies the same code to a mouse-drag scenario to illustrate that events can be handled in the same manner.
- Events and Arrays are both collections, just with different interfaces. Arrays use an iterator pattern. Events use an observer pattern. Jafar explains why he believes these two patterns are similar and why Events and Arrays should be handled in the same way.
Observables
- Observables are important because they are capable of modeling events, async server requests, and animations. To create observables in JavaScript, Jafar will be using the open source Reactive Extensions library.
- While addressing an audience question, Jafar provides a real-world metaphor to further explain the difference between observers and iterators. He also walks through the implementation of the Observable.fromEvent() method.
- Jafar demonstrates how Observables would work with the functions he introduced earlier. He runs examples using map(), filter(), and concatAll() and talks about the results.
- Using observables can help eliminate race conditions since they sequence the incoming streams. They also are able to handle scenarios with nested observables (observables of observables). Jafar revisits his cake-cutting scenario to further explain nested observables.
- The takeUntil method copies all the data from a source observable into a new observable. However it completes once it reaches a “stop observable” which is passed as a parameter. This allows a seemingly infinite stream of data become finite.
- Now that Jafar has covered the concatAll() and takeUntil() methods, he revisits the mouse-move code. This demonstrates how user interface events can be reduced to simple collections and handled in a similar way to arrays.
- The mergeAll() method functions similarly to the concatAll() method except that mergeAll will combine subsequent observables without waiting for a previous one to complete. Jafar explains why mergeAll can be useful and also covers the final flattening patter, switchLatest().
- Jafar combines all the techniques he’s discussed up to this point to illustrate how to build the Netflix auto-suggest search box. The box will throttle key presses to limit network request and concatenate the received data until a new observable comes along.
- Jafar spends a couple minutes talking about an optimized version of the search box code. He also explains the purpose of the retry method. Jafar also answers a number of audience questions about the different methods in this example.
- Using the Netflix player example from earlier in the course, Jafar walks through the code that takes the tangled callback version of the player and converts it into a clean, three-dimensional collection.
Creating Array Functions
- Jafar introduces the exercises and guides the class through the first five which lead up to implementing a map function. Each exercise is written and run in the browser. If an exercise is completed correctly, it will reveal the next exercise.
- The next set of exercises involve filtering and flattening. Jafar demonstrates how to implement the filter and concatAll functions which can be used in more complex chaining. This leads to exercise 11 which requires the use of both map and concatAll.
- In exercise 12, you will retrieve the id, title, and box art URL for every video in the collection. Before beginning the exercise, Jafar gives a few instructions to ensure only asynchronous-compatible code will be used.
- In exercise 13, you will create a concatMap function that can be used to simplify consecutive concat/map calls. Exercise 14 puts this new function to use.
- In these exercises, you will begin working with a reduce function. The reduce function performs operations on array items at the same time as opposed to one item at a time.
- Exercise 18 involves using both the reduce and map functions to reduce multiple boxart objects to a single value. Exercise 19 demonstrates how to have the reduce function return a different type than the accumulator. Jafar also talks briefly about prototypical inheritance.
- Exercise 20 combines many of the functions implemented in earlier exercises including reduce, filter, and concatMap.
- When information is organized based on its position in an array, a zipping operation may be required to combine elements from equal positions in each array. Exercise 21 explains the need for zipping, exercise 22 implements a custom zip function, and exercise 23 puts this new function to work.
- In exercise 24, you will retrieve each video’s id, title, middle interesting moment time, and smallest box art. This will require using most of the function created throughout all the exercises.
Creating Trees
- Jafar spends a few minutes talking about debugging. When working with asynchronous code, step-into and step-over statements are not always as effective. Jafar suggests using the debugger directive and setting breakpoints.
- Before continuing with more exercises, Jafar draws a few comparisons between Sequel code and the map/filter/concatAll functions written in earlier exercises. The JavaScript code is very similar to JOIN operations in Sequel.
- Exercise 25 puts all five of the operators created in earlier exercises to use. The task is to convert Array data into tree structures that possess parent-child relationships.
- Jafar begins the lengthy 26th exercise by setting up the multiple levels of mapping required. He also gives a few tips about logging progress before running any concatenation. This makes it easier to verify all the desired data has been pulled into the collection correctly.
- Jafar finishes exercise 26 by zipping the some of the nested datasets to form the final collection.
- Exercise 27 marks the first exercise where live, asynchronous data is queried. The stock ticker will continuously log the data as new packets arrive.
Handling Events with Observables
- These exercises demonstrate how to transition from using explicit DOM events to Observables. Jafar also introduces the take function which will automatically dispose the subscription to the Observable after it has completed.
- Exercise 31 introduces the takeUntil function which will continue to pull data from a stream until a stop observable is encountered. Similarly to the take function, takeUntil will also dispose once the stopping point is reached.
- Before starting exercise 32, Jafar spends some time explaining how to respond to UI events wrapped in Observables. Execution code is placed inside a forEach so it can be run each time a new event is added to the collection.
- Jafar reviews the anatomy of an Observable. An Observable is nothing more than an object with a forEach function. The observer referenced when creating the Observable will have onNext, onError, and onCompleted functions.
- To further demonstrate how Observables operate, Jafar converts the JavaScript setTimeout function into an Observable. He then compares this implementation to the Observable.fromEvent code in the Reactive Ex library.
- Jafar describes the differences between Observables and Promises. He also spends a few minutes talking about how Observables compare to Node streams and what Observables may look like in ES7.
- In this exercise, you will create a mouse drag event using Observables. To do this, you will retrieve only the mouse down events that occur before the next mouse up event.
- Jafar points out the mouse drag code in the previous exercise has a couple issues. The mouse snaps to the upper left corner of the object whenever it is grabbed. Jafar uses the offsetX and offsetY properties to fix this issue.
Handling HTTP Requests with Observables
- Most HTTP requests are exposed through a callback API. This exercise demonstrates how to use the getJSON method in jQuery to load remote data and handle success/error events. Jafar also begins building a larger example that will wrap the getJSON method in an Observable. First, he needs to get input from the user.
- Jafar uses JSONP to perform a search using the Wikipedia API because it will bypass any cross-origin issues. While his search function is still using callbacks, it demonstrates the API is working and allows him to them move it from a callback to an Observable.
- Now that Jafar has a working JSONP call, he converts it into an Observable. This creates the forEach and dispose functions required for subscribing to the Observable. When JSON data is received, the Observable calls the onNext and onCompleted.
- As the forEach function is called on the JSONP Observable, Jafar breaks down what the incoming data is going to look like to better explain which functions will be necessary to compose the stream.
- Jafar uses the map and switchLatest functions to compose the search results into a dataset that will populate the autocomplete box. The switchLatest function is the key for optimizing the behavior since it will dispose any of the previous requests.
- To further optimize the search suggestions, Jafar what only changed values to be sent to the server. While there are a number of ways to implement this, he chooses to introduce the RX.distinctUntilChanged function which will only update the stream when a change has occurred.
- Jafar demonstrates how to handle errors that may occur when making network requests. The error handler is passed as the second parameter to the forEach and the retry function can be used to designate the number of attempts the Observable should make. This error handler will get called if after the desired number of attempts has been reached.
- After answering a few audience questions, Jafar further optimizes the code by only performing searches when the search text is not empty. He uses the filter function to check for values
- Jafar modifies the user interface so the search box is hidden by default and will be shown when the user clicks a Search button. This will allow him to demonstrate how to make the search subscription dependent on the search button being clicked.
- After adding a close button to the search form, Jafar wants the click event from that button to dispose the current search stream and hide the form. To do this, he creates an observable from the click event and uses it in a takeUntil function.
- Jafar adds the correct functionality to the close button so it will hide the form, thus disposing the current stream of server request. He also talks for a few minutes about how to introduce side effects during the forEach cycle with the doAction function.
- Before moving on, Jafar spends takes some time to answer audience questions about the behavior of the form and some other general questions about Observables.
Observable In-Depth
- Up to this point, Jafar has been using the Observable class from the RX library. To better explain how Observables work under the hood, he creates an Observable class from scratch and implements the forEach and fromEvent functions.
- Jafar revisits the implementation for the map function. Only this time, instead of adding it to the Array class, he implements it on the Observable class. Since it is on the Observable class, map will call onNext and pass the appropriate projection function.
- The Observable filter function has a similar implementation to the map function. Jafar leads the group through adding this function and explains the public forEach function with a little more detail.
- Now that Jafar has created his own Observable class with a map and filter function, he builds a simple program to see it in action. When a button is clicked, he transforms the mouse position value with the map function and returns a filtered result.
- The Object.observe API will be landing in ES7. While it does allow developers to monitor for changes in variables, the API has its pitfalls. Jafar demonstrates how this API can be recreated as an Observable by implementing the take function. -
- With the take function implemented, Jafar uses it to convert the Object.observe function into an Observable. This allows him to fix some of the pitfalls in the API.
- Jafar puts his new Observable based on the Object.observe API to work by creating a two-way binding between the model data and the view. If the view is updated, the changes propagate to the model. If the model is updated, the changes are reflected in the view.
- While two-way binding in the application is nice, the changes reflected in the model and view should also be synchronized with the database. Jafar expands his example to include a database request as the model data is changed.
- Jafar wraps up the course talking about how Observables can be used to sequence animations in a user interface. He also revisits the concept of syncing data with a database.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops