/** @module concurrency */
/**A **Promise.all** that does not fails-fast.
* Given N promises will return all of them <u>independenly if they failed or not</u>.
* @see [Fail-fast](https://en.wikipedia.org/wiki/Fail-fast)
* @see [Rob-Pike](https://www.youtube.com/watch?v=f6kdp27TYZs)
* @see [concurrencyTest.js](https://github.com/nerac/keyu/blob/master/test/concurrencyTest.js)
* @argument {Array(Promise)} promises An array of all promises to be executed
* @returns {Array(Object)}
* @example
* await full([Promise.resolve(1), Promise.reject(2), Promise.resolve(3)])
* // [ { value: 1 }, { error: 2 }, { value: 3 } ]
* @see [concurrencyTest.js](https://github.com/nerac/keyu/blob/master/test/concurrencyTest.js)
* @method
*/
const full = promises => Promise.all(promises.map(promise => promise.then(value => ({ value })).catch(error => ({ error }))));
/** Given **N promises** will return <u>the fastest non-failed one</u>.
* This pattern can be useful some times to reduce latency.
* @see [When Do Redundant Requests Reduce Latency?](https://ieeexplore.ieee.org/document/7348681)
* @see [Rob-Pike](https://www.youtube.com/watch?v=f6kdp27TYZs)
* @argument {Array(Promise)} promises An array of all promises to be executed
* @returns {Promise}
* @example
* await best([Promise.resolve(1),Promise.resolve(2)]) // -> 1 (assuming 1 is the first to resolve)
* await best([Promise.reject(1),Promise.resolve(2)]) // -> 2
* @see [concurrencyTest.js](https://github.com/nerac/keyu/blob/master/test/concurrencyTest.js)
* @method
*/
const best = promises =>
new Promise((resolve, reject, errors = []) => {
promises.map(promise =>
promise.then(resolve).catch(err => {
errors.push(err);
if (errors.length === promises.length) {
reject(errors);
}
})
);
});
module.exports = { best, full };