In this course, we start from the beginning, rebuilding and rethinking why we async, and how. We solve the same problem over and over, each time with a different async pattern. By the end, we’ve seen and practices all the major async patterns, so we have a more concrete sense of the pros/cons.
Advanced JS, Web Performance & Realtime Node.js
Parallel vs. Async
- 00:00 - 11:46 Course Introduction Kyle Simpson (@getify) begins his course on Async Patterns with a brief introduction of himself and an overview of the course agenda. He runs a few open source projects like LabJS, Grips, and Asynquence. He is also the head of curriculum for the developer/engineer training school Maker Square.
- 16:45 - 24:55 Concurrency Kyle introduces concurrency as two higher-level tasks happening within the same timeframe. He illustrates these higher-level tasks or macro-tasks might be composed of many micro-tasks. As each micro-task is initiated, it queues up behind any other existing tasks and is executed in order.
- 24:56 - 29:35 Callback Hell Kyle describes callbacks as a continuation of code. One part of the program executes, then later, another part of the program continues. He also introduces “callback hell” and makes the argument that the classic sideways pyramid shape has nothing to do with the inherent problems created by callbacks.
- 29:36 - 34:12 Exercise 1 The code in exercise 1 will be reimplemented throughout the next seven exercises. Each time you will be using a different async pattern. In this exercise, you will write async flow-control code while only using callbacks.
- 34:13 - 46:15 Exercise 1 Solution Kyle walks through the solution to exercise 1.
- 46:16 - 58:36 Callback Problems: Inversion of Control In the context of callbacks, inversion of control is the notion of having code under your control in one part of the program, then handing control over to a callback in another part of the program. Kyle explains why inversion of control is one of two major problems with callbacks and shares a few problem scenarios.
- 58:37 - 01:07:05 Callback Problems: Not Reason-able The second problem with callbacks is they don’t handle divergent code very well. Kyle describes this as not being reasonable or understandable. His goal is to write async code that looks synchronous and sequential. This can’t be done with callbacks alone.
- 01:07:06 - 01:11:43 Non Fixes Kyle spends a few minutes showing a number of “non fixes” for callbacks. These are techniques that have been developed to make callbacks more reliable, however they tend to introduce their own side effects.
- 01:11:44 - 01:23:54 Synchronous and Asynchronous Thunks Thunks are functions that already have everything they need to return a value. They do not require any parameters. Kyle explains how thunks typically manifest themselves as a function wrapper around some state or token value. Hey also demonstrates the difference between synchronous and asynchronous thunks.
- 01:23:55 - 01:26:33 Exercise 2 In this exercise, you will write the same async flow-control code using thunks instead of callbacks.
- 01:26:34 - 01:38:44 Exercise 2 Solution Kyle walks through the solution to exercise 2.
- 01:38:45 - 01:44:22 Thunks and Closure After completing exercise 2, Kyle spends a few minutes diving deeper into the relationship between thunks and closure. Thunks use closure to maintain state and eliminate the factor of time in asynchronous code.
- 01:44:23 - 01:51:42 Native Promises Promises represent a placeholder for a future value. They solve the inversion of control issue that exists with callbacks by providing completion events for asynchronous tasks. This puts the control back inside the application.
- 01:51:43 - 02:01:25 Promise API Using the checkout example, Kyle introduces the native Promise API. He also explains that even though promises appear to use callbacks, there is a increased level of trust. Promises will only resolve once, will have either a success or error outcome, and are immutable once resolved.
- 02:01:26 - 02:08:29 Promise Flow Control Promises manage sequential flow controls through chaining. Promises are chained together when one promise returns a subsequent promise in its success handler. Kyle shares a few of the previous code examples reimplemented with promise chaining.
- 02:08:30 - 02:09:55 Exercise 3 In this exercise, you will use promises to implement the flow-control code for retrieving files.
- 02:09:56 - 02:18:42 Exercise 3 Solution Kyle walks through the solution to exercise 3.
- 02:18:43 - 02:28:32 Exercise 3 Questions Part 1 Kyle spends some time answer audience questions about exercise 3.
- 02:28:33 - 02:39:20 Exercise 3 Questions Part 2 Kyle continues answering audience questions about exercise 3 before moving on to the next exercise.
- 02:39:21 - 02:42:21 Exercise 4 In this exercise, you will modify the promise-based flow control code so it can be used with any number of steps.
- 02:42:22 - 02:53:36 Exercise 4 Solution Kyle walks through the solution to exercise 4.
- 02:53:37 - 03:02:37 Abstractions Kyle introduces a few abstractions in the promise API. Promise.all() takes in an array of promises and will wait for all promises in the array to resolve. Promise.race() also receives an array of promises, however, it only waits for whichever promise in the array resolves or rejects first.
03:02:38 - 03:10:05
Sequences & Gates
While native promises provide some API for chaining and sequencing, rewriting the logic each time can be redundant. This led Kyle to create the open source library Asynquence. His library adds a number of abstraction methods which make sequencing and gating promises easier.
- 03:10:06 - 03:11:15 Exercise 5 & 6 In these exercises, you will use the Asynquence library to get the list of files. For exercise 5, the Asynquence will replace the code in exercise 3. Exercise 6 will apply Asynquence to the exercise 4 solution.
- 03:11:16 - 03:21:00 Exercise 5 Solution Kyle walks through the solution to exercise 5.
- 03:21:01 - 03:34:21 Exercise 6 Solution Kyle walks through the solution to exercise 6.
- 03:34:22 - 03:43:12 Generator Example Generators are a new type of function in ES6. In asynchronous programming, generators solve the non-sequential, non-reasonable issues of callbacks. When a generator is called, it returns an iterator which will step through the generator, pausing anytime the yield keyword is encountered. After introducing the concept of a generator, Kyle shares a simple code example.
- 03:43:13 - 03:52:51 Messaging If the yield keyword in a generator is called with a value, that value will be returned to the iterator along with a “done” boolean value. This allows messages to be sent outside of the generator. Kyle explains why this is useful and also demonstrates that subsequent calls to the next() method can be used to pass message back into the generator.
- 03:52:52 - 04:02:21 Messaging Questions Kyle spends a few minutes reviewing the way generators send and receive messages. He also answers a number of audience questions about generators, iterators, and the use of the yield keyword.
- 04:02:22 - 04:12:45 Async Generators Kyle demonstrates how generators can be used in asynchronous applications. The yield keyword will block a generator while an async call is being executed. Values returned from the async call can be passed back to the generator allowing it to resume and sequentially trigger other async operations.
- 04:12:46 - 04:25:47 Promises + Generators While generators completely solve the issue of sequencing asynchronous operations, they are still susceptible to inversion of control. Since promises solve the inversion of control issue, Kyle explains how they should be combined with generators to create better asynchronous code.
- 04:25:48 - 04:26:45 Exercise 7 In this exercise, you will now use generators to write the async flow control code from the previous exercises.
- 04:26:46 - 04:36:06 Exercise 7 Solution Kyle walks through the solution to exercise 7.
- 04:36:07 - 04:39:59 Quiz Kyle spends a few minutes quizzing the audience on the async patterns he’s covered up to this point.
- 04:40:00 - 04:45:35 Events + Promises Promises work well with asynchronous events that occur once. A stream of events, however, make promises more difficult to use because a promise can only be resolved once. Kyle explains a few of the ways promises could work with event streams but stresses the need for and alternative solution.
04:45:36 - 04:58:16
04:58:17 - 05:09:07
Reactive sequences are the implementation of observables that Kyle added into Asynquence. Kyle introduces the API for creating a reactive sequence and shares a few code examples. The power of a reactive sequence lies in the ability for it to be composed with other sequences.
- 05:09:08 - 05:11:14 Exercise 8 In this exercise, you will create your own streams and stream responses.
- 05:11:15 - 05:23:32 Exercise 8 Solution Part 1 Kyle walks through the solution to exercise 8.
- 05:23:33 - 05:29:55 Exercise 8 Solution Part 2 Kyle continues the exercise 8 solution by answering a few audience questions.
- 05:29:56 - 05:42:16 Concurrency + Channels CSP or, Communicating Sequential Processes, involves modeling concurrency through channels. These channels use blocking techniques to send and receive messages. After explaining some of the concepts behind CSP, Kyle shares a simple code example.
- 05:42:17 - 05:50:52 Blocking Channels Kyle further explores how blocking channels are implemented in CSP. In this case, the messaging occurs inside an infinite loop. The yield keyword will block the loop while waiting to put a message into the channel or take a message from the channel.
- 05:50:53 - 05:56:43 Event Channels Kyle spends a few minutes explains how CSP can be applied to DOM events. He also demonstrates how he uses CSP inside of the Asynquence library.
- 05:56:44 - 05:57:17 Exercise 9 In this exercise, you will implement that same functionality as in exercise 8 while only using CSP.
- 05:57:18 - 06:09:58 Exercise 9 Solution Kyle walks through the solution to exercise 9.
06:09:59 - 06:18:09
Kyle summarizes the various async patterns he covered through the course. This includes callbacks/thunks, promises, generators, observables and CSP. He also shows his “Tale of Three Lists” demonstration which highlights the differences in some of these patterns.
- 06:18:10 - 06:20:45 Exercise 10 Kyle assigns exercise 10 as an extra credit exercise. It involves implementing the Tale of Three Lists example using either reactive sequences or CSP.
- 06:20:46 - 06:22:53 Wrap-up Kyle concludes his course on Async Patterns with a few final thoughts.