前哨
for await
なんて便利な物があるではないか
以下そのまま転載
const asyncIterable = {
[Symbol.asyncIterator]() {
return {
i: 0,
next() {
if (this.i < 3) {
return Promise.resolve({ value: this.i++, done: false });
}
return Promise.resolve({ done: true });
}
};
}
};
(async function() {
for await (let num of asyncIterable) {
console.log(num);
}
})();
// 0
// 1
// 2
つまり内部に Promise
や await
があるイテレータを for
ループで回せる訳ですね。
とすれば配列にたくさん Primise
ぶちこんで、こんなかんじに回してあげれば逐次実行できる訳です。
// 関数を遅延実行できるようにする
lazyFunction = (f, ...args) => {
return () => f(...args)
}
async executePromiseSerearize(ps) {
const rs = []
// ps を頭から実行するイテレータを作る
const executer = async function*(ps){
const _ps = [].concat(ps)
while(_ps.length){
const p = _ps.shift()
yield await p()
}
}
// イテレータを for of で実行
for await(const r of executer(ps)){
rs.push(r)
}
return rs
}
// 1秒後に n が出力されて n が帰ってくる
const hogehoge = (n) => new Promise((resolve, reject) => {
setTimeout(() => {
console.log(n)
resolve(n)
}, 1000)
})
const ps = [1,2,3,4,5].map(n => lazyFunction(hogehoge, n))
!(async () => {
res = await executePromiseSerearize(ps)
console.log(res)
})()
// 1 から 5 が1秒毎に出力されて最後に配列が出る
でも eslint では非推奨
書いてある事をざっくり言うと 「なんで async
でプロセスが並列で処理できるのに逐次実行しようとするの??なんで時間の無駄遣いをしようとするの??バカなの??*ぬの???」
という事ですが……例えばさぁ……WEBスクレイピングするのに何万ページ一気に開いてアクセスするとか……もうDDoS攻撃レベルじゃないですか……
というわけで
非推奨の物でも、使わなきゃいけない事がある。おします。