コード
const all = <T>(...promises: ReadonlyArray<PromiseLike<T>>): Promise<Array<T>> => {
if (promises.length === 0) {
return Promise.resolve<Array<T>>([]);
}
let rejected = false;
const map: Map<number, T> = new Map();
return new Promise<Array<T>>((resolve, reject) => {
promises.forEach((p: PromiseLike<T>, i: number) => {
p.then((t: T) => {
if (rejected) {
return;
}
map.set(i, t);
if (map.size === promises.length) {
const values: Array<T> = [];
for (let i = 0; i < map.size; i++) {
values.push(map.get(i)!);
}
resolve(values);
}
}, (e: unknown) => {
if (rejected) {
return;
}
rejected = true;
reject(e);
});
});
});
};
がんばったところ
- たとえ
Promise(Like)
の終了(fulfilledになる)順番が配列のとおりでなくても、与えられた配列の順番のとおりに解決された値の配列を返す - 途中で例外が投げられた場合、そこで処理を中断する。そのとき例外がいくつあろうと初めの例外を返す
感想
なんとなく使っているPromise.all()
だが、大まかな動作だけを再現するならそこまで難しくはなかった。