假设我有60项任务,每项任务至少需要30分钟。现在我想一次只运行5个,所以当这5个中的1个完成时,另一个任务会被执行直到所有任务完成。
最干净的方法是什么?这个模式有名字吗?
答案 0 :(得分:3)
我建议使用bluebird
Promise.map
方法,在val map = dataSnapshot.getValue(Map::class.java) as Map<String, String>
的情况下,您可以将其配置为使用并发方法。
答案 1 :(得分:0)
一种解决方案是编写一个帮助程序类来为您执行此操作。我必须自己多次使用这个模式,所以我有这个实用程序类来管理一组promises并允许一次运行不超过指定的限制:
class PromiseLimitQueue {
constructor(limit) {
if (Math.floor(limit) <= 0) throw new Error("Limit must be a positive integer.");
this._limit = Math.floor(limit);
this._head = [];
this._queue = [];
}
// The promFunc must be a function that returns a promise, not a promise itself.
// Method returns a new promise that resolves when the promise that promFunc
// returns has run and resolved.
enqueue(promFunc) {
return new Promise((resolve, reject) => {
const newFunc = () => promFunc().then(resolve).catch(reject);
this._queue.push(newFunc);
if (this._head.length < this._limit) this._pullNext();
});
}
_pullNext() {
const next = this._queue.shift();
if (!next) return;
const prom = next();
const onDone = () => {
const index = this._head.indexOf(prom);
if (index !== -1) this._head.splice(index, 1);
this._pullNext();
}
prom.then(onDone, onDone);
this._head.push(prom);
}
}
// Usage Example:
// Helper function returns a promise that resolves after 'num' milliseconds.
function timer(num) {
return new Promise(resolve => {
setTimeout(resolve, num)
})
}
// Create a new limit queue, give desired limit (in this case, 5);
const limitQueue = new PromiseLimitQueue(5);
// Queue up 20 1-second timers, observe that only 5 ever run at once:
for (let i = 0; i < 20; i++) {
limitQueue.enqueue(() => timer(1000)).then(() => console.log(`Timer ${i} Resolved.`))
}