我在一次调用 10 个异步函数的自定义异步队列中遇到了一个错误。
我正在启动包含 50 个作业的队列,一旦前 10 个作业完成,队列就会移动到后续的 10 个作业,直到完成所有作业。
我遇到的错误是,一旦它完成 50 个,它就会重新开始前 5 个作业,一次有 2 个或 3 个或 1 个作业。它还需要不到 10 个作业到队列末尾。
请创建这两个文件并使用 mocha 进行测试并自行查看输出。
注意:将 mocha 中的超时设置为 0 以保持测试长时间运行。
Queue.js
function Queue(func, max) {
this.jobs = [];
this.func = func;
this.max = max ? max : 10;
}
Queue.prototype.push = function(data) {
var self = this;
return new Promise(function(resolve, reject){
self.jobs.push({data: data, resolve: resolve, reject: reject});
if(!self.progress) {
self.progress = true;
self.run();
}
});
};
Queue.prototype.run = function() {
var self = this;
var tasks = [];
console.log("--------------------");
for(var i=0; i<this.jobs.length && i < this.max; i++) {
tasks.push(this.jobs.shift());
console.log("queuing", tasks[tasks.length-1].data);
}
console.log("Total jobs queued", tasks.length);
Promise.all(
tasks.map(function(task){
return self.func(task.data)
.then(task.resolve, task.reject);
}
)).then(this.next.bind(this));
};
Queue.prototype.next = function(){
if(this.jobs.length) {
this.run();
} else {
this.progress = false;
}
};
module.exports = Queue;
QueueTest.js
function async(data) {
return new Promise(function(resolve, reject){
setTimeout(function(){
console.log("resolving", data);
resolve(data);
}, Math.random() * 5000);
});
}
it("should test queue", function(done){
var queue = new Queue(async);
Promise.all(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50].map(queue.push.bind(queue))
).then(function(){
done();
});
});
最佳答案
问题出在Queue.prototype.run
中的for
循环
我无法立即明白为什么它会像现在这样行为不端,但解决方法是用 self.jobs.splice()
替换 for
循环来创建tasks
数组。
Queue.prototype.run = function() {
console.log("--------------------");
var self = this;
var tasks = self.jobs.splice(0, self.max); // <<<<<<<< this is the fix
console.log("tasks:", tasks.map(obj => obj.data));
Promise.all(
tasks.map(function(task){
return self.func(task.data)
.then(task.resolve, task.reject);
}
)).then(this.next.bind(this));
};
没有其他需要改变的。
关于javascript - 具有最大并发性的异步并发队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47719780/