2016-11-03 7 views
0

私はNodeJSバックエンドサービスで作業しており、約束を使ってデータをロードしています。さて、私は、さまざまなソースからのアイテムの組み合わせ(配列)を作りたいと思っています。私は以下の解決策を持っていますが、これがこのようなことを回避する正しい方法だとは思わないのです。 ループ(ノード)での約束の使用

var results = []; 
loop(items, index, data, results).then(function() { 
    console.log(results); 
}); 

function loop(items, index, data, results) { 
    return utils.getPromise(function(resolve, reject) { 
     if (index === items.length) { 
      // Stop 
      resolve(); 
     } else { 
      doAction(items[index], data).then(function(result) { 
       if (result) { 
        mergeResults(results, result) 
       } else { 
        loop(items, index + 1, data, results).then(resolve, reject); 
       } 
      }, reject); 
     } 
    }); 
} 

function doAction(item, data) { 
    return utils.getPromise(function(resolve, reject) { 
     item.doIt(data).then(resolve, reject); 
    }); 
} 

私は正しい道はすぐに約束を返し、その場で結果を追加することだと思うが、私はこれを行う方法を正確に知りません。助言がありますか?

答えて

4

Promise.allを使用して、約束のすべての結果を集めることができます。 .all promise自体は、各約束のすべての単一の結果を含む配列で解決されます。

私は、正しい方法は、あなたがあなただけの約束を返し、これらの約束から配列を作成し提案のように、すぐに

約束を返すことになると思います。ループの後、この配列をPromise.allに渡します。 @Tobiが言うのように

var promiseArray = []; 
for(var i=0;i<array.length;i++){ 
    promiseArray.push(doSomethingAsync(array[i])); 
} 
Promise.all(promiseArray).then(function(responseArray){ 
    //do something with the results 
}); 
1

function randTimeout(t) { 
 
    return new Promise(function (resolve) { 
 
    setTimeout(function() { 
 
     console.log('time done:' + t); 
 
     resolve(); 
 
    }, t); 
 
    }); 
 
} 
 

 
var timeouts = []; 
 
for (var l = 0; l < 20; l ++) { 
 
    timeouts.push(Math.random() * 1000 | 0); 
 
} 
 

 
console.log('start'); 
 
Promise.map(timeouts, function (t) { 
 
    return randTimeout(t); 
 
}, {concurrency: 3});
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.4.6/bluebird.min.js"></script>

、あなたがPromise.Allを使用することができます。..

しかしPromise.allは1つの落とし穴があります。

は、次のようになります! !

あなたの処理にはたくさんの項目があり、多くの項目を送信して同時にいくつかの非同期作業を行うのは最適ではないかもしれません。そして、不可能な場合もあります。ノードで一度に多数のファイルを開くと、ハンドルエラーが多すぎます。

Bluebird約束ライブラリには、mapという便利な機能があり、並行処理と呼ばれるオプションがあります。これにより、一度にX個の約束を処理することができます。個人的には、並行処理オプションを持つマップ関数はとても便利なので、Promise仕様の一部でなければならないと思います。並行性オプションを使用しないと、配列を最初に作る必要なしにpromise.allを実行するのと同じ効果があります。

上記の例では、最大20秒のランダムタイムアウトを作成しました。マップを使用しないと、すべての約束が一度に実行されるため、これを実行する最大時間は1秒になります。しかし、同時実行性オプション3を使用すると、一度に3回実行され、表示されているように完了までに1秒以上かかります。