Como faço para retornar os resultados acumulados de várias chamadas de funções assíncronas (paralelas) em um loop?

Eu tenho uma funçãofoo que faz várias chamadas assíncronas (paralelas) em um loop. De alguma forma, preciso esperar até que os resultados de todas as chamadas estejam disponíveis. Como posso retornar os resultados completos defooou acionar algum processamento apóstudo dos dados está disponível?

Tentei adicionar cada resultado a uma matriz, mas a matriz não será preenchida até depois do ponto em que preciso usá-lo.

function foo() {
    var results = [];

    for (var i = 0; i < 10; i++) {
      someAsyncFunction({someParam:i}, function callback(data) {
        results.push(data);
      });
    }
    return results;
}

var result = foo(); // It always ends up being an empty array at this point.

Nota: esta questão é deliberadamente genérica, de acordo com as linhas genéricas existentes."Como eu retorno a resposta de uma chamada assíncrona?" Pergunta, questão. Essa pergunta tem algumas respostas excelentes, mas não cobre várias chamadas assíncronas. Existem algumas outras perguntas que mencionam várias chamadas, mas não consegui encontrar nenhuma baseada em loop, e algumas só tiveram respostas jQuery, etc. Espero aqui algumas técnicas genéricas que não dependem de uma biblioteca específica.

questionAnswers(4)

yourAnswerToTheQuestion