Dado um Array de funções assíncronas, retorne uma nova Promise. Elas não aceitam argumentos e cada uma retorna uma Promise. Todas devem ser resolvidas em paralelo.

O desafio consistia em criar a minha própria versão de Promise.all.

Promise resolve:

Quando todas as Promises das funções retornarem com sucesso em paralelo. O valor resolvido da Promise deve ser um array com todos os valores resolvidos das funções, na ordem que foram definidas no array.

Promise reject:

Quando uma Promise for rejeitada. A Promise final também deve usar o primeiro motivo de rejeição que receber.


Example 1:

Input: functions = [
  () => new Promise(resolve => setTimeout(() => resolve(5), 200))
]
Output: {"t": 200, "resolved": [5]}
Explanation:
promiseAll(functions).then(console.log); // [5]

A única função foi resolvida em 200ms com o valor 5.

Example 2:

Input: functions = [
    () => new Promise(resolve => setTimeout(() => resolve(1), 200)),
    () => new Promise((resolve, reject) => setTimeout(() => reject("Error"), 100))
]
Output: {"t": 100, "rejected": "Error"}
Explanation: Como uma das Promises foi rejeitada, a Promise retornada também foi rejeitada com o mesmo erro no mesmo momento.

Example 3:

Input: functions = [
    () => new Promise(resolve => setTimeout(() => resolve(4), 50)),
    () => new Promise(resolve => setTimeout(() => resolve(10), 150)),
    () => new Promise(resolve => setTimeout(() => resolve(16), 100))
]
Output: {"t": 150, "resolved": [4, 10, 16]}
Explanation: Todas as Promises foram resolvidas com sucesso. A Promise retornada foi resolvida quando a última Promise terminou.


Solução implementada

/**
 * @param {Array<Function>} functions
 * @return {Promise<any>}
 */
var promiseAll = function(functions) {
    return new Promise((resolve, reject) => {
        let results = [];
        let completed = 0;

        if (functions.length === 0) {
            resolve([]);
        }

        for (let i = 0; i < functions.length; i++) {
            functions[i]()
                .then(value => {
                    results[i] = value;
                    completed++;
                    if (completed === functions.length) {
                        resolve(results);
                    }
                })
                .catch(err => reject(err)); // rejeita se alguma Promise falhar
        }
    });
};

/**
 * const promise = promiseAll([() => new Promise(res => res(42))])
 * promise.then(console.log); // [42]
 */


Explicação da solução

Para resolver, primeiro criei um array vazio chamado results[] e uma variável chamada completed = 0. Eles são usados para: