ES7 introduces async functions, which allow you to write asynchronous code with a synchronous syntax. Unfortunately this doesn't work well with AngularJS: awaited code will run outside of Angular's digest loop, and therefore it won't trigger watchers or view updates.
ES7 introduces async functions that allow to write async code with a synchronous syntax. This looks like this:
This works because
await expects a promise as arguments, and it waits until the promise is resolved before continuing.
Unfortunately this doesn’t work well in AngularJS: awaited code is not run in the digest loop, and therefore we need to put
$scope.$apply calls all over the place. This results in code like this:
Obviously this isn’t ideal, it would be better if we could omit the
Fortunately there is a way out. Thanks to the generator functions introduced in ES6 we can write our own async engine that does work well with AngularJS. At Magnet.me we’ve created the $async module which does exactly that. With
$async we can rewrite the initialize function like this:
Instead of an async function we now use a generator function passed to
$async, and instead of
awaiting a promise we now
yield a promise.
How it works
Generator functions do not run to completion when they are invoked. Instead they return an iterator that can be iterated over manually. This iterator will stop and “return” at every call to
yield. For example, the following generator function generates all positive integers:
$async module makes use of the ability to pause generator functions to emulate async functions. It expects a generator that will generate promises, and it will chain all these promises together correctly. The result is that each
yield call will wait for its promise to be resolved before continuing. The core of
$async looks something like this:
Now that we have our own async engine it is trivial to make it work properly with Angular: we can add the call to
$scope.$apply in the
iterateAsync function and there it is: an async function that works with AngularJS!
The entire module is only a couple of lines long, if you’re interested in all the details then check it out here!
To give credit where credit’s due, the idea of using generators to implement aysnc functions isn’t new. Libraries that do so exist for a long time, with the most well-known being co.
$async is mostly inspired by
co, but more lightweight and Angular-flavored.