Notes from ForwardJS – Advanced JS: Rethinking Async

These are some notes-to-self from Kyle Simpson‘s recenct ForwardJS workshop titled: Advanced JS: Rethinking Async.

The Problem: Callback Hell

  • Limitations placed on our flow control, imposed by callback syntax.
  • Inability to trust how your callback will be handled.

Concepts: Parallel vs Async

  • Parallel = all 30 people on the same rollercoaster car.
  • Async = 30 people on 30 1-seater rollercoaster cars one after the next.

Concurrency

  • Temporal dependency – when a concurrent task depends on going before/after another concurrent task.
  • Our brains are a good model of concurrency: “multi-tasking”

Inversion of Control

  • You call libraries, frameworks call you.
  • An async/callback model hands over (inverts) control to somewhere else in the system. This hands the control over, which can lead to complexity.
    • Example: passing a callback to a 3rd party tracking function that calls your chargeCreditCard() method. If they push some experimental code that tries to retry the callback X number of times after a fixed timeout, the credit card gets charged multiple times. Not good.

Bugs

Bugs are more likely to happen when the way our brain works is different from how the code actually works behind the scenes.

 

The way we plan is the way we code, and this is typically sequential.

 

The way we express our code is fundamentally different from the way our brains think.

Thunks

NOTE TO SELF: this still does not make much sense to me – read more 🙂

In computer programming, a thunk is a subroutine that is created, often automatically, to assist a call to another subroutine

Wikipedia

A function that has everything it needs (no args required, maybe a callback).

– Kyle

Synchronous example:
var thunk = function() { return 10 + 20; };

  • Old school method for handling race conditions and async.
  • Thunk = time-independent wrapper around a future value.

Promises

  • A way of promising a future value.
  • A callback manager that addresses the “trust problems” associated with callback hell.

Analogy:

  • Order a cheeseburger.
  • Get a receipt (not the actual cheeseburger) = reference (promise) to future cheeseburger.
  • At some future point, the number on receipt is called and the cheeseburger arrives.

Plusses:

  • Promises are a way to preserve control of the callback (rather than “inverting” control).
  • Promises natively handle all the issues associated with callback hell: risk of being called more than once, silent errors, etc.

Chaining Promises:

  • This is how we get basic flow control.
  • Method: return the nth + 1 promise from the success handler of the nth promise, which causes the subsequent .then() to only resolve when the nested promise resolves.

Looks something like:

Promise Abstractions

Promise.all()
Takes an array of promises and then resolves them all with a callback that is passed a results array, with indexes matching the original promises array.

Promise.race()
Pass an array of promises with one timer/placeholder promise that includes base timeout that returns a reject() response within a settimeout(). The function returns the first promise to resolve. This is a method for implementing a timeout for multiple promises.

Asynquence

https://github.com/getify/asynquence

  • Promise-style async sequence flow-control made by Kyle
  • This library is essentially a handy wrapper for promises that makes writing and reading promise-based code much clearer.

Generators

Example: function* gen() {...}

  • Paused by yield;
  • Resumed by iterator.next(); (where iterator = gen())

* Note that yield/next() only pause the internal workings of the generator, not your entire JS environment.

  • Generators allow us to implement the otherwise complicated go/pause patterns that our brains tend to like.
  • One potential issue is that we still have a callback, which means we’re again inverting control, hence. . .

Generators + Promises

Takes the above pattern and simply returns a promise (we control) instead passing a callback. Confusing? Yes. But ends up with very simple code:

 

Looking back at what we might have without using Promises/Generators at all, it looks pretty awesome:

Observables

rxjs.codeplex.com

RxJS or Reactive Extensions for JavaScript is a library for transforming, composing, and querying streams of data. We mean all kinds of data too, from simple arrays of values, to series of events (unfortunate or otherwise), to complex flows of data.

Here’s a neat example using Kyle’s Asynquence library:

 

1 thought on “Notes from ForwardJS – Advanced JS: Rethinking Async”

Leave a Reply

Your email address will not be published. Required fields are marked *