最近非常に興味深い問題が発生しました。背景には、httpリクエストを同時に起動し、各応答の結果を配列で取得したいということです。また、要求のすべての約束が解決されると、。 私は2つの方法で実装しようとしましたが、異なる結果が得られることがありました。Promise.allのスケジュール順はPromise.allでグループ化すると約束します
次のコードスニペット(httpHelper.get
はBlueBirdの約束を返します)をご覧ください。 溶液A:
function solutionA() {
var requestOptions = [...]; // an array of request options
var promises = [];
var results = [];
_.forEach(requestOptions, function(requestOption){
var promise = httpHelper.get(requestOption).then(function singleThenCallBack(response){
//Using this solution, sometimes this code won't execute from some response, I guess it's because the Promise.all.then gets executed before this then.
results.push(response.body.result);
});
promises.push(promise);
});
return Promise.all(promises).then(function allThenCallBack(){
return results;
});
}
溶液B:
function solutionB() {
var requestOptions = [...]; // an array of request options
var promises = [];
var results = [];
_.forEach(requestOptions, function singleThenCallBack(requestOption){
var promise = httpHelper.get(requestOption);
promises.push(promise);
});
return Promise.all(promises).then(function allThenCallBack(responses){
_.forEach(responses, function(response){
results.push(response.body.result);
});
return results;
});
}
だから、A液を使用することの問題点は、時々singleThenCallBack
機能は、いくつかの応答で呼び出されることはありません、ということですので、 results
には私が得るべきすべての結果が含まれていません。 解決策Bは常にすべての結果が配列results
にプッシュされることを保証します。私は、Promise
とPromise.all
のためにthen
がどのようにスケジュールされるのかが原因だと思う。 私の質問は、解決策Aでpromises
がPromise.then
の約束であるべきではないということです。それではallThenCallBack
の機能に達する前に、すべての応答のために関数singleThenCallBack
が呼び出されるべきですか?
誰かが私にこの行動の理由を説明してくれることを願っています。ありがとう!
編集:
var Promise = require("bluebird");
var promises = [];
var promise1 = new Promise(function(resolve, reject){
setTimeout(function() {
resolve(1);
}, 5000);
});
var thenPromise1 = promise1.then(function(value){
console.log("********* resolved promise1 *********: " + value);
console.log(promise1);
return 0.1;
}, console.log("*****This means then function is called synchronously."));
promises.push(thenPromise1);
thenPromise1.then(function(value){
console.log("********* resolved thenPromise1 *********: " + value);
console.log(thenPromise1);
});
var allPromise = Promise.all(promises);
allPromise.then(function(value){
console.log("********* resolved allPromise *********: " + value);
console.log(allPromise);
});
console.log("********* promise1 *********");
console.log(promise1);
console.log("********* thenPromise1 *********");
console.log(thenPromise1);
console.log("********* allPromise *********");
console.log(allPromise);
console.log("***********code end*************");
、出力は次のとおりです: だから私は、次のコードで連鎖する約束を証明するためにいくつかのコードを実行しようとした出力で
*****This means then function is called synchronously.
********* promise1 *********
{ _bitField: 1,
_fulfillmentHandler0: [Function],
_rejectionHandler0: undefined,
_promise0:
{ '2': 0,
'3':
{ _promise: [Object],
_values: [Object],
_length: 1,
_totalResolved: 0 },
_bitField: 2,
_fulfillmentHandler0: [Function],
_rejectionHandler0: undefined,
_promise0:
{ _bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined,
_trace: [Object] },
_receiver0: undefined,
_trace: { [Error] _parent: undefined, _promisesCreated: 0, _length: 1 } },
_receiver0: undefined,
_trace: { [Error] _parent: undefined, _promisesCreated: 0, _length: 1 } }
********* thenPromise1 *********
{ '2': 0,
'3':
{ _promise:
{ _bitField: 134217729,
_fulfillmentHandler0: [Function],
_rejectionHandler0: undefined,
_promise0: [Object],
_receiver0: undefined },
_values: [ [Circular] ],
_length: 1,
_totalResolved: 0 },
_bitField: 2,
_fulfillmentHandler0: [Function],
_rejectionHandler0: undefined,
_promise0:
{ _bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined,
_trace: { [Error] _parent: undefined, _promisesCreated: 0, _length: 1 } },
_receiver0: undefined,
_trace: { [Error] _parent: undefined, _promisesCreated: 0, _length: 1 } }
********* allPromise *********
{ _bitField: 134217729,
_fulfillmentHandler0: [Function],
_rejectionHandler0: undefined,
_promise0:
{ _bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined,
_trace: { [Error] _parent: undefined, _promisesCreated: 0, _length: 1 } },
_receiver0: undefined }
***********code end*************
********* resolved promise1 *********: 1
{ _bitField: 33554433,
_fulfillmentHandler0: [Function],
_rejectionHandler0: 1,
_promise0: undefined,
_receiver0: undefined,
_trace: { [Error] _parent: undefined, _promisesCreated: 0, _length: 1 } }
********* resolved thenPromise1 *********: 0.1
{ '2': 0,
'3':
{ _promise:
{ _bitField: 134217729,
_fulfillmentHandler0: [Function],
_rejectionHandler0: undefined,
_promise0: [Object],
_receiver0: undefined },
_values: [ [Circular] ],
_length: 1,
_totalResolved: 0 },
_bitField: 33554434,
_fulfillmentHandler0: [Function],
_rejectionHandler0: 0.1,
_promise0: undefined,
_receiver0: undefined,
_trace: { [Error] _parent: undefined, _promisesCreated: 0, _length: 1 } }
********* resolved allPromise *********: 0.1
{ _bitField: 167772161,
_fulfillmentHandler0: [Function],
_rejectionHandler0: [ 0.1 ],
_promise0: undefined,
_receiver0: undefined }
、thenPromise1
オブジェクトは_promise0
です。これはthenPromise1.then(...)
によって作成された約束です。 '3'
の後の約束オブジェクトはPromise.all(...)
によって作成された約束です。つまり、この約束は常にthenPromise1
の後に連鎖されています。 質問が無効で、他の部分で何かが間違っていたと思います。
ここで、コード内の 'results'の数を確認しますか? –
ここには示されていませんが、SolutionA/B関数の呼び出し元です。 –
あなたは本当に 'forEach' +' push'の代わりに 'map'を使うべきです – Bergi