Table of Contents
Parallel vs. Async
Course IntroductionKyle 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.
ConcurrencyKyle 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.
Callback HellKyle 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.
Exercise 1The 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.
Exercise 1 SolutionKyle walks through the solution to exercise 1.
Callback Problems: Inversion of ControlIn 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.
Callback Problems: Not Reason-ableThe 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.
Non FixesKyle 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.
Synchronous and Asynchronous ThunksThunks 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.
Exercise 2In this exercise, you will write the same async flow-control code using thunks instead of callbacks.
Exercise 2 SolutionKyle walks through the solution to exercise 2.
Thunks and ClosureAfter 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.
Native PromisesPromises 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.
Promise APIUsing 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.
Promise Flow ControlPromises 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.
Exercise 3In this exercise, you will use promises to implement the flow-control code for retrieving files.
Exercise 3 SolutionKyle walks through the solution to exercise 3.
Exercise 3 Questions Part 1Kyle spends some time answer audience questions about exercise 3.
Exercise 3 Questions Part 2Kyle continues answering audience questions about exercise 3 before moving on to the next exercise.
Exercise 4In this exercise, you will modify the promise-based flow control code so it can be used with any number of steps.
Exercise 4 SolutionKyle walks through the solution to exercise 4.
AbstractionsKyle 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.
Sequences & GatesWhile 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.
Exercise 5 & 6In 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.
Exercise 5 SolutionKyle walks through the solution to exercise 5.
Exercise 6 SolutionKyle walks through the solution to exercise 6.
Generator ExampleGenerators 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.
MessagingIf 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.
Messaging QuestionsKyle 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.
Async GeneratorsKyle 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.
Promises + GeneratorsWhile 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.
Exercise 7In this exercise, you will now use generators to write the async flow control code from the previous exercises.
Exercise 7 SolutionKyle walks through the solution to exercise 7.
QuizKyle spends a few minutes quizzing the audience on the async patterns he’s covered up to this point.
Events + PromisesPromises 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.
Reactive SequencesReactive 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.
Exercise 8In this exercise, you will create your own streams and stream responses.
Exercise 8 Solution Part 1Kyle walks through the solution to exercise 8.
Exercise 8 Solution Part 2Kyle continues the exercise 8 solution by answering a few audience questions.
Concurrency + ChannelsCSP 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.
Blocking ChannelsKyle 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.
Event ChannelsKyle 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.
Exercise 9In this exercise, you will implement that same functionality as in exercise 8 while only using CSP.
Exercise 9 SolutionKyle walks through the solution to exercise 9.
RecapKyle 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.
Exercise 10Kyle assigns exercise 10 as an extra credit exercise. It involves implementing the Tale of Three Lists example using either reactive sequences or CSP.
Wrap-upKyle concludes his course on Async Patterns with a few final thoughts.