Javascript 使用JS承诺或生成器并行执行最多N个任务

Javascript 使用JS承诺或生成器并行执行最多N个任务,javascript,ecmascript-6,generator,es6-promise,Javascript,Ecmascript 6,Generator,Es6 Promise,我想实现一个JS类,它使用JS承诺或生成器并行执行最多N个任务。差不多 class Executor { constructor(numberOfMaxTasks) { ... } next(task) { ... } done(onDone) { ... } } .... const executor = new Executor(2); executor.next(task1).next(task2).next(t

我想实现一个JS类,它使用JS承诺或生成器并行执行最多N个任务。差不多

class Executor {
    constructor(numberOfMaxTasks) {
    ...
    }

    next(task) {
    ...
    }

    done(onDone) {
    ...
    }
}

....
const executor = new Executor(2);
executor.next(task1).next(task2).next(task3).done(onDone);
task1和Task2应并行执行,而task3应等待前一个任务完成。当所有任务完成时,执行一个回调


我试图用承诺来实现它,但失败了。我是发电机新手,目前不知道他们是否能在这里提供帮助。这主要是为了学习,这就是为什么我不想使用任何第三方库,只使用原生JS。任何提示都很好,提前谢谢

最近,我不得不为一次面试做一个小测验,这个测验与您想要达到的目标类似,但基于Node.js
关键是使用类属性控制同时执行的任务量(在我的示例中,
this.running
)。因此,对于一系列任务,您可以通过while循环运行它们,并检查每个循环中是否有可用的插槽(由this.running和LIMIT控制),然后运行promise。
这段代码可能会对您有所帮助

    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);
              }
            });      
          }   
        }
    }
let tasks=[];
让tasksDone=[];
常数限值=10;
类执行器{
构造函数(){
此参数为0;
for(设i=0;i<1000;i++){
任务[i]={
id:“作业”+(i+1),
时间:((i%4)+1)*25
};
}
}
checkConcurrency(){
if(this.running>LIMIT){
抛出新错误('达到最大任务数['+限制+']);
}
}
执行(任务){
返回新承诺((解决、拒绝)=>{
这个是.running++;
这是checkConcurrency();
设置超时(()=>{
这是checkConcurrency();
这个,跑,;
决心({
任务
完成日期:Date.now()
});
},任务。时间);
})
}
运行(){
this.startTime=Date.now();
this.executeTasks(tasks.slice(0));
}
执行任务{
while(this.running0){
让task=tasks.shift();
执行(任务)。然后(结果=>{
tasksDone.push(结果);
如果(tasks.length>0){
这是执行任务;
}
});      
}   
}
}

我想你最好使用

例如,哪个可以做你想做的事:

  • 在第一个参数中,您可以指定任务执行所需的数据数组
  • 在第二个参数中,您可以指定mapper函数,它可以实际运行您的任务并返回承诺
  • 在第三个参数中,您可以使用
    {concurrency:N}
    对象指定“当时最多N个任务”
请注意,对于
bluebird.map
函数,不能保证执行顺序。唯一可以保证
bluebird.map
的结果将以相同顺序的结果数组得到满足

使用该函数,您可以在无需执行器类的情况下重写代码(例如node.js):

const Promise=require('bluebird'))
常量os=require('os')
常量task1Data=1000
常数task2Data=5000
常量task3Data=3000
常量tasksData=[task1Data,task2Data,task3Data]
函数taskExecutorMapper(taskData){
//这里是实际运行的代码的位置
//基于taskData和返回承诺的异步操作
//我将在这里使用setTimeout来模拟这种操作
返回新承诺(函数(解析){
setTimeout(解析,任务数据)
}
}
const tasksPromise=Promise.map(
任务数据,
taskExecutionMapper,
{并发:os.cpus().length})
.然后(onDone)

希望这有帮助!

您知道JavaScript不会并行运行代码,除非您正在生成WebWorkers或node.js等效程序,对吧?Promissions和其他异步程序允许您在运行非JavaScript程序(网络IO等)时运行代码在后台继续。请告诉我们您尝试了什么。不要再为异步代码使用生成器。直接使用
async
/
wait
语法。可能重复@Touffy是的,您是对的。也许并行不是最好的词。我对这个标题有点困惑:。可能是异步而不是并行w会更好的。