Execute Asynchronous Functions in Parallel O(n) solution
IntuitionAt first I thought we'd need 2 loops, 1 to call the promises and a 2nd loop to await their results.eg:
loop #1 -> init promises
loop #2 -> await each p
# Intuition\nAt first I thought we\'d need 2 loops, 1 to call the promises and a 2nd loop to await their results.\n\neg: \nloop #1 -> init promises\nloop #2 -> await each promise\n\nThen, I remembered that this a synchronous function, so we won\'t have access to the \'await\' keyword.\n\n# Approach\nSo, we can keep a count of how many promises are \'finished\' by incrementing a variable in our top-most closure.\n\nWhenever a promise is finished, it will increment the counter.\n\nWe\'ll also need to save the results, so to keep the order of the original call stack.  We init a same-sized array as our parameter \'functions\' and initialize each value with null.\n\nWhenever the last promise finishes, it will hit the condition\n\ndoneCount === functions.length\n\neg, functions = [fn1, fn2]\n    doneCount = 2\n    => time to resolve our promise.all call\n\n# Complexity\n- Time complexity:\n\nO(n), we have 1 loop so n it is.\n\n\n- Space complexity:\nO(n).  We have to copy a same-sized array of our functions parameter & can disregard the counters / how javascript manages promises.\n\n\n# Code\n```typescript []\ntype Fn<T> = () => Promise<T>\n\nfunction promiseAll<T>(functions: Fn<T>[]): Promise<T[]> {\n    let doneCount = 0\n    const results = Array(functions.length).fill(null)\n\n    return new Promise<T[]>((resolve, reject) => {\n        if (functions.length <= 0) { resolve([]) }\n        for (let i = 0; i < functions.length; i++) {\n            functions[i]().then((res) => {\n                results[i] = res\n                if (++doneCount === functions.length) { resolve(results) }\n            }).catch((e) => reject(e))\n        }\n    })\n};\n\n/**\n * const promise = promiseAll([() => new Promise(res => res(42))])\n * promise.then(console.log); // [42]\n */\n```
['TypeScript', 'JavaScript']