Last active
March 29, 2018 09:03
-
-
Save Semigradsky/45b4f9628360f812b3640fa979f3a1c4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(() => { | |
class Parallel { | |
constructor({ parallelJobs }) { | |
this.parallelJobs = parallelJobs; | |
this.jobsQueue = []; | |
this.results = []; | |
} | |
_flatten(arrray) { | |
return arrray.reduce((acc, value) => acc.concat(value), []); | |
} | |
_runParallel(jobs, done) { | |
let countCollectedValues = 0; | |
const values = []; | |
function collectValues({ index, value }) { | |
values[index] = value; | |
countCollectedValues++; | |
if (countCollectedValues === jobs.length) { | |
done(values); | |
} | |
} | |
jobs.forEach((job, index) => job((value) => collectValues({ index, value }))); | |
} | |
_runEach(actions, done) { | |
let countCollectedValues = 0; | |
const values = []; | |
function collectValues({ index, value }) { | |
values[index] = value; | |
countCollectedValues++; | |
if (countCollectedValues === actions.length) { | |
done(values); | |
} else { | |
doAction(); | |
} | |
} | |
function doAction() { | |
const action = actions[countCollectedValues]; | |
action((value) => collectValues({ index: countCollectedValues, value })) | |
} | |
doAction(); | |
} | |
_doWithLimit(actions, limit, done) { | |
let actionsCopy = [...actions]; | |
const jobsBatches = []; | |
while (actionsCopy.length) { | |
const limitedActions = actionsCopy.slice(0, limit); | |
jobsBatches.push((done) => { | |
setTimeout(() => { | |
this._runParallel(limitedActions, done); | |
}, 0) | |
}); | |
actionsCopy = actionsCopy.slice(limit); | |
} | |
this._runEach(jobsBatches, done); | |
} | |
job(callback) { | |
this.jobsQueue.push(callback); | |
return this; | |
} | |
done(callback) { | |
this._doWithLimit(this.jobsQueue, this.parallelJobs, (results) => { | |
callback(this._flatten(results)); | |
}); | |
} | |
} | |
const runner = new Parallel({ | |
parallelJobs: 2 | |
}); | |
let result = 'before/'; | |
runner | |
.job(step0) | |
.job(step1) | |
.job(step2) | |
.job(step3) | |
.job(step4) | |
.done(onDone); | |
result += 'after/'; | |
function step0(done) { | |
console.log('step0'); | |
result += 'step0/'; | |
done('step0'); | |
} | |
function step1(done) { | |
console.log('step1'); | |
result += 'step1/'; | |
setTimeout(done, 3000, 'step1'); | |
} | |
setTimeout(() => result += 'after0-1/', 2500); | |
function step2(done) { | |
console.log('step2'); | |
result += 'step2/'; | |
setTimeout(done, 1500, 'step2'); | |
} | |
function step3(done) { | |
console.log('step3'); | |
result += 'step3/'; | |
setTimeout(done, 2000, 'step3'); | |
} | |
setTimeout(() => result += 'after2-3/', 4500); | |
function step4(done) { | |
console.log('step4'); | |
result += 'step4/'; | |
setTimeout(done, 500, 'step4'); | |
} | |
setTimeout(() => result += 'after4/', 5500); | |
let isPassed = false; | |
function onDone(results) { | |
console.log('onDone', results, result); | |
console.assert(Array.isArray(results), 'expect result to be array'); | |
console.assert(results.length === 5, 'the results length must be 5'); | |
console.assert(results[0] === 'step0', 'Wrong answer 1'); | |
console.assert(results[1] === 'step1', 'Wrong answer 2'); | |
console.assert(results[2] === 'step2', 'Wrong answer 2'); | |
console.assert(results[3] === 'step3', 'Wrong answer 3'); | |
console.assert(results[4] === 'step4', 'Wrong answer 4'); | |
console.assert(result === 'before/after/step0/step1/after0-1/step2/step3/after2-3/step4/after4/', 'Wrong steps'); | |
console.log('Thanks, all works fine'); | |
isPassed = true; | |
} | |
setTimeout(() => { | |
if(isPassed) return; | |
console.error('Test is not done.'); | |
}, 6000); | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(() => { | |
class Parallel { | |
constructor({ parallelJobs }) { | |
this.parallelJobs = parallelJobs; | |
this.jobsQueue = []; | |
this.results = []; | |
} | |
async _runAsync(action) { | |
return new Promise((resolve) => { | |
setTimeout(() => { | |
resolve(action()); | |
}, 0) | |
}); | |
} | |
async _runParallel(actions) { | |
return Promise.all( | |
actions.map((action) => new Promise(resolve => action(resolve))) | |
); | |
} | |
async _doWithLimit(actions, limit) { | |
let actionsCopy = [...actions]; | |
let results = []; | |
const actionsBatches = []; | |
while (actionsCopy.length) { | |
const limitedActions = actionsCopy.slice(0, limit); | |
actionsBatches.push(limitedActions); | |
actionsCopy = actionsCopy.slice(limit); | |
} | |
for (const actions of actionsBatches) { | |
const res = await this._runAsync(() => this._runParallel(actions)); | |
results = results.concat(res); | |
} | |
return results; | |
} | |
job(callback) { | |
this.jobsQueue.push(callback); | |
return this; | |
} | |
async done(callback) { | |
const results = await this._doWithLimit(this.jobsQueue, this.parallelJobs); | |
callback(results); | |
} | |
} | |
const runner = new Parallel({ | |
parallelJobs: 2 | |
}); | |
let result = 'before/'; | |
runner | |
.job(step0) | |
.job(step1) | |
.job(step2) | |
.job(step3) | |
.job(step4) | |
.done(onDone); | |
result += 'after/'; | |
function step0(done) { | |
console.log('step0'); | |
result += 'step0/'; | |
done('step0'); | |
} | |
function step1(done) { | |
console.log('step1'); | |
result += 'step1/'; | |
setTimeout(done, 3000, 'step1'); | |
} | |
setTimeout(() => result += 'after0-1/', 2500); | |
function step2(done) { | |
console.log('step2'); | |
result += 'step2/'; | |
setTimeout(done, 1500, 'step2'); | |
} | |
function step3(done) { | |
console.log('step3'); | |
result += 'step3/'; | |
setTimeout(done, 2000, 'step3'); | |
} | |
setTimeout(() => result += 'after2-3/', 4500); | |
function step4(done) { | |
console.log('step4'); | |
result += 'step4/'; | |
setTimeout(done, 500, 'step4'); | |
} | |
setTimeout(() => result += 'after4/', 5500); | |
let isPassed = false; | |
function onDone(results) { | |
console.log('onDone', results, result); | |
console.assert(Array.isArray(results), 'expect result to be array'); | |
console.assert(results.length === 5, 'the results length must be 5'); | |
console.assert(results[0] === 'step0', 'Wrong answer 1'); | |
console.assert(results[1] === 'step1', 'Wrong answer 2'); | |
console.assert(results[2] === 'step2', 'Wrong answer 2'); | |
console.assert(results[3] === 'step3', 'Wrong answer 3'); | |
console.assert(results[4] === 'step4', 'Wrong answer 4'); | |
console.assert(result === 'before/after/step0/step1/after0-1/step2/step3/after2-3/step4/after4/', 'Wrong steps'); | |
console.log('Thanks, all works fine'); | |
isPassed = true; | |
} | |
setTimeout(() => { | |
if(isPassed) return; | |
console.error('Test is not done.'); | |
}, 6000); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
test01 - первый вариант на коллбеках
test02 - второй вариант на промисах