`Async.jankYielder` is known to, unfortunately, cause jank by creating a lot of
immediately resolved promises that must be then GCed. For a collection of 50
items, it will create 50 promises and 49 of them will immediately resolve.
Instead of `Async.jankYielder`, we now have `Async.yieldState`, which simply
keeps track of whether or not the caller should yield to the event loop. Two
higher level looping constructs are built on top of it:
* `Async.yieldingIterator`, which has been rewritten to not create extraneous
promises; and
* `Async.yieldingForEach`, which is a replacement for awaiting
`Async.jankYielder` in a loop. Instead, it accepts the loop body as a
function.
Each of these can share an instance of an `Async.yieldState`, which allows an
object with multiple loops to yield every N iterations overall, instead of
every N iterations of each loop, which keeps the behaviour of using one
`Async.jankYielders` in multiple places.
Differential Revision: https://phabricator.services.mozilla.com/D26229