promise-parallel-throttle
同時に実行できるPromiseの数を抑えたもの
2023-01-11 05:58:24 再実装
TypeScriptで書く
arrow functionsにする
mod.tsexport type Fn = <T>() => Promise<T>;
export const makeThlottle = <T>(max: number): (job: Fn<T>) => Promise<T> => {
const queue: [
Fn<T>,
(value: T) => void,
(error: unknown) => void
][] = [];
const pendings = new Set<Promise<T>>();
const runNext = async (prev: Promise<T>) => {
pendings.delete(prev);
const task = queue.shift();
if (!task) return;
const promise = task[0]()
.then((result) => task[1](result))
.catch((error) => task[2](error));
pendings.add(promise);
promise.finally(() => runNext(task[0]));
};
return (job) => {
if (pendings.size < max) {
const promise = job();
pendings.add(promise);
promise.finally(() => runNext(promise));
return promise;
}
return new Promise((resolve, reject) => {
queue.push([job, resolve, reject]);
});
};
};
2021-03-13 05:59:58
promiseCallbacks
にPromiseを生成する関数を渡す
Promiseそのものではなく、生成する関数を使うことで、Promiseの開始を遅延できる
script.jsexport async function throttle(promiseCallbacks, {maxInProgress = undefined} = {}) {
if (!maxInProgress || maxInProgress < 0
|| promiseCallbacks.length <= maxInProgress)
return await Promise.all(promiseCallbacks.map(callback => callback()));
let progressList = promiseCallbacks.map(_ => false);
let result = [];
await Promise.all([...Array(maxInProgress).keys()]
.map(async index => {
do {
//console.log(`Executing index ${index}...`);
progressList[index] = true;
result[index] = await promiseCallbacks[index]();
//console.log(`Executed ${index}.`);
index = progressList.findIndex(state => !state);
} while(index !== -1)
}));
return result;
}
script.d.tsexport function throttle<T, U>(
promiseCallbacks: ((...params: T) => Promise<U>)[],
options?: {maxInProgress?: number},
): Promise<U[]>;