Beyond mere JavaScript alone, this has the following example of a .WhenAll in C# for spinning up multiple asynchronous tasks to run at once while not acting upon them until they are all done "coming back" as it were.
IEnumerable<Task<int>> downloadTasksQuery = from url in urlList select
ProcessURLAsync(url);
Task<int>[] downloadTasks = downloadTasksQuery.ToArray();
int[] lengths = await Task.WhenAll(downloadTasks);
int total = lengths.Sum();
The collection of similar things above however isn't really a real world work scenario. Instead more likely you will find yourself grabbing three things from three different web services (which will get aggregated into one POCO to return from a method containing calls to methods for the three calls) and wanting to call out "here kitty, kitty" for all the cats at once instead of calling for Patches, waiting her to come home, calling for Fluffy, waiting for him to come home too, and finally calling for Shadow and waiting for him to come in as well. Well, this has the following example of making breakfast that works with diversified concerns:
private static async Task<BreakFast> MakeBreakFast()
{
var taskToastBread = ToastBreadAsync();
var taskBoilEggs = BoilEggsAsync();
var taskMakeTea = MakeTeaAsync();
await Task.WhenAll (new Task[] {taskToasBread, taskBoilEggs, taskMakeTea});
return new BreakFast()
{
Toast = taskToastBread.Result,
Eggs = taskBoilEggs.Result,
Tea = taksMakeTea.Result,
}
}
In the example ToastBreadAsync returns a Task of Toast and BoilEggsAsync a Task of Eggs and thus it is perfectly fine for the tasks to be of differing return types. You can still add them to an array of tasks after all. You do not have to new up the array right in the middle of the .WhenAll. You could have made a variable for it upstream. Also, you may use a List of Task instead of an array too. The "playback head" is not going to move beyond the .WhenAll line until all of the cats have come home. There are going to be times when this pattern doesn't work as not everyone can eat at once however.
In a scenario in which you have to get something from the first web service to be able to feed the call to the second web service to begin with and then what you get back from that is furthermore required to call the third web service, then there is nothing you can do with .WhenAll and some actors just have to wait for other actors upstream to act. ("playback head" is a term from a Macromedia Director training book out of the 1990s and I apologize for using it here)