配列をforEachでまわし、内側で走る非同期処理がすべて終了したタイミングをひろい、次の処理に続けたい場合どのような方法があるでしょうか?node.js で keyの配列をforEachでまわし、内側でredis-client.get()を利用するケースを想定しています。
下記の方法で目的の動作はできているのですが、何かスマートじゃないような...
そもそも、forEach?また、まだ利用できていないのですが、generatorを使って次の処理をsleepしておく方法?などもありそうな気がしています。他に良い方法があれば教えていただければ幸いです。よろしくお願いします。
var keysArr = ['a','b','c','d','e','f','g','h','i','j','k','l'];
var forEachWithAsync = function(arr) {
return new Promise(function(resolve) {
var cnt = 0;
console.log('length: ' + arr.length);
arr.forEach(function(val, idx, arr) {
// node_redis client.get(key, function(err, val) {...}); を使うケースを想定
setTimeout(function() {
++cnt;
console.log(cnt + ' async log: ' + val);
if(cnt === arr.length) { resolve(); }
}, Math.round(Math.random()*10000));
});
});
}
forEachWithAsync(keysArr)
.then(function() { console.log('end'); });
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+4
これの出番です.
せっかくなのでES6の機能ふんだんに使って書きます.
(Node.jsということなので,特にブラウザの互換性のような問題も気にしなくていいと思います)
'use strict';
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const keys = ['a','b','c','d','e','f','g','h','i','j','k','l'];
Promise.all(keys.map(
value => sleep(Math.round(Math.random()*10000)).then(() => console.log('done: ' + value))
)).then(
() => console.log('[all done]'), // すべてresolveされた
e => console.error(e) // ひとつでもrejectされた,または例外がスローされた
);
co+Generatorを使うならもう少し見やすくかけますね.
'use strict';
const co = require('co');
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const keys = ['a','b','c','d','e','f','g','h','i','j','k','l'];
co(function* () {
yield keys.map(function* (value) {
yield sleep(Math.round(Math.random()*10000));
console.log('done: ' + value);
});
console.log('[all done]');
}).catch(e => console.error(e));
Babelでコンパイルする前提でasync/awaitを使うなら
'use strict';
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const keys = ['a','b','c','d','e','f','g','h','i','j','k','l'];
(async () => {
await Promise.all(keys.map(async value => {
await sleep(Math.round(Math.random()*10000));
console.log('done: ' + value);
}));
console.log('[all done]');
})().catch(e => console.error(e));
/*
coを使うけどよりPromiseやasync/awaitとの親和性を高くして書く場合もこのように
co(function* () {
yield Promise.all(keys.map(value => co(function* () {
yield sleep(Math.round(Math.random()*10000));
console.log('done: ' + value);
})));
console.log('[all done]');
}).catch(e => console.error(e));
*/
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
個人的には setTimeout()
だけで完結させる方法をとります。
setTimeout
'use strict';
setTimeout(function timeout (array, i, resolve) {
console.log(i, array[i]);
if (++i < array.length) {
setTimeout(timeout, Math.round(Math.random()*10000), array, i, resolve);
} else {
resolve(array);
}
}, Math.round(Math.random()*10000), ['a','b','c','d','e','f','g','h','i','j','k','l'], 0, function resolve (array) { console.log('finished!'); });
setTimeout Polyfill (for IE9-)
setTimeout
の第3引数は IE9- 未対応なので Polyfill を適用させます。
Re: bleurouge さん
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/04/15 21:16
2016/04/15 21:28
2016/04/16 00:47