そもそもそんな複雑なことしないほうが...
まあそうですね…
今回のタイミングで改めてPromiseやArrayまわりと向き合ったのでメモ
#直列処理
const task = (label, timeout) => {
return () => {
return new Promise((resolve, reject) => {
console.log(`${label} start`);
setTimeout(() => {
console.log(`${label} done`);
//timeout秒経ったら次へ
resolve();
}, timeout);
});
}
};
console.log('promise start');
Promise.resolve()
.then(task('task1', 100))
.then(task('task2', 200));
こんな処理が3回とかだったらまだいいかもしれないが、これが多数となったらこのままthenで続けるような記述をするのはつらすぎる…
そこでArray#reduceを使って記述してみる
Array.prototype.reduce() - JavaScript | MDN
#Array#reduceを使って直列繋ぎ
promise-reduce.js
const task = (label, timeout) => {
return () => {
return new Promise((resolve, reject) => {
console.log(`${label} start time: ${timeout}`);
setTimeout(() => {
console.log(`${label} done`);
//timeout秒経ったら次へ
resolve();
}, timeout);
});
}
};
const REPEAT = 10;
[...Array(REPEAT).keys()].reduce((promise, current) => {
let label = `task${current}`;
let timeout = Math.floor((Math.random() * 500));
return promise.then(task(label, timeout));
}, Promise.resolve());
結果
$node promise-reduce.js
task0 start time: 69
task0 done
task1 start time: 5
task1 done
task2 start time: 191
task2 done
task3 start time: 89
task3 done
task4 start time: 458
task4 done
task5 start time: 112
task5 done
task6 start time: 107
task6 done
task7 start time: 14
task7 done
task8 start time: 284
task8 done
task9 start time: 183
task9 done
並列×直列処理
この個数が更に増えたら、ちょっとだけ並列にも動かしたい。
でも結果は同時にほしい
promise-parallel-serial.js
const task = (label, timeout) => {
return () => {
return new Promise((resolve, reject) => {
console.log(`start: ${label} time: ${timeout}`);
setTimeout(() => {
console.log(`done: ${label} time: ${timeout}`);
//timeout秒経ったら次へ
resolve();
}, timeout);
});
}
};
//直列処理は3つ
const REPEAT = 3;
//並列は4つ
const PARALLEL = 4;
const parallels = [...Array(PARALLEL).keys()].map(index => {
let lastpromise = [...Array(REPEAT).keys()].reduce((promise, current) => {
let label = `task ${index+1}-${current+1}`;
let timeout = Math.floor((Math.random() * 500));
return promise.then(task(label, timeout));
}, Promise.resolve());
return lastpromise;
});
Promise.all(parallels).then(() => {
//並列実行したすべてが完了したとき
console.log('all done');
});
結果
start: task 1-1 time: 179
start: task 2-1 time: 26
start: task 3-1 time: 199
start: task 4-1 time: 303
done: task 2-1 time: 26
start: task 2-2 time: 469
done: task 1-1 time: 179
start: task 1-2 time: 365
done: task 3-1 time: 199
start: task 3-2 time: 36
done: task 3-2 time: 36
start: task 3-3 time: 360
done: task 4-1 time: 303
start: task 4-2 time: 474
done: task 2-2 time: 469
start: task 2-3 time: 331
done: task 1-2 time: 365
start: task 1-3 time: 82
done: task 3-3 time: 360
done: task 1-3 time: 82
done: task 4-2 time: 474
start: task 4-3 time: 47
done: task 4-3 time: 47
done: task 2-3 time: 331
メモ
- Promise.allはthenをまとめてるだけ。
- async/awaitのほうがわかりやすいだろうな