我想实现一个JS类,它使用JS promises或generator并行执行最多N个任务。像
这样的东西class Executor {
constructor(numberOfMaxTasks) {
...
}
next(task) {
...
}
done(onDone) {
...
}
}
....
const executor = new Executor(2);
executor.next(task1).next(task2).next(task3).done(onDone);
任务1和任务2应该并行执行,而task3应该等到上一个任务结束。当所有任务完成onDone时,执行回调。
我试图用promises实现它,但我失败了。我是发电机的新手,目前不知道他们是否可以在这里提供帮助。这主要是出于学习目的,这就是为什么我不想使用任何第三方库,只是原生JS。任何提示都会很棒,提前谢谢!
答案 0 :(得分:0)
最近我不得不为你想要实现的面试解决一个测验,但是基于 Node.js 。
关键是使用类属性控制正在执行的任务量(在我的示例中为 let tasks = [];
let tasksDone = [];
const LIMIT = 10;
class Executor {
constructor () {
this.running = 0;
for (let i = 0; i < 1000; i++) {
tasks[i] = {
id: 'job_' + (i+1),
time: ((i % 4) + 1) * 25
};
}
}
checkConcurrency () {
if( this.running > LIMIT ){
throw new Error('Maximum number of tasks ['+LIMIT+'] reached');
}
}
execute (task) {
return new Promise((resolve, reject)=>{
this.running ++;
this.checkConcurrency();
setTimeout(()=>{
this.checkConcurrency();
this.running --;
resolve({
...task,
finished: Date.now()
});
}, task.time);
})
}
run () {
this.startTime = Date.now();
this.executeTasks(tasks.slice(0));
}
executeTasks(tasks) {
while (this.running < LIMIT && tasks.length > 0) {
let task = tasks.shift();
this.execute(task).then( result => {
tasksDone.push(result);
if (tasks.length > 0) {
this.executeTasks(tasks);
}
});
}
}
}
)。因此,对于一系列任务,您可以通过while循环运行它们并检查每个循环,如果您有任何可用的插槽(由this.running和LIMIT控制),然后运行promise。
此代码可能对您有所帮助。
{{1}}
答案 1 :(得分:0)
我认为您最好使用bluebird promise library。
例如,bluebird provides map
function可以做你想做的事情:
{ concurrency: N }
对象。请注意,对于bluebird.map
函数,执行顺序并不保证。唯一可以保证bluebird.map
的结果将以相同顺序的结果数组实现。
使用该函数,您可以在不使用Executor
类的情况下重写代码(示例适用于node.js):
const Promise = require('bluebird')
const os = require('os')
const task1Data = 1000
const task2Data = 5000
const task3Data = 3000
const tasksData = [ task1Data, task2Data, task3Data ]
function taskExecutorMapper(taskData) {
// here is place for your code that actually runs
// asynchronous operation based on taskData and returns promise
// I'll use setTimeout here for emulate such operation
return new Promise(function(resolve) {
setTimeout(resolve, taskData)
}
}
const tasksPromise = Promise.map(
tasksData,
taskExecutionMapper,
{ concurrency: os.cpus().length })
.then(onDone)
希望这有帮助!