Guard against concurrent array mutation in Async.doInParallel

If the array of items processed by `Async.doInParallel` is augmented concurrently, the returned master promise may neither resolve nor reject. This is because resolution and rejection happen only when total number of resolved or rejected promises reaches the current size of the array of items, which, if augmented, is now larger than the total number of promises. Of course, failure of some sort is unsurprising with concurrent modification, but this simple adjustment---counting down from the initial array length instead of counting up to the current array length---eliminates this particular problem and is also slightly more efficient.

This PR also removes code that creates an array with the generated promises and then promptly throws it away.