こんにちは、
map(...)を使用しているときに、iteratee関数から発行されたエラーを処理して、提供されたコレクションからまだ処理されていないアイテムの数を判別する方法はありますか?
map
を使用して、さまざまなurlsparamsなどの配列に対して複数の送信HTTPリクエストを実行しています(ノードrequest
ライブラリを使用)。これらのリクエストのいずれかを実行する途中で、特定のエラーが発生する場合があります。処理できるターゲット サーバーから取得できますが、作業中の現在のアイテムと、 map
がまだ取得していない残りのアイテムを再処理したいと思います。
コレクション内の正常に処理された(エラーなしの)各アイテムにフラグを設定し、関心のあるエラーが発生した場合は、それに応じて処理するのではないかと思いました。 次に、まだ処理されていないアイテムに対してフラグをfalseに設定してアイテムから新しい配列を作成し、これらに対してさらにmap
を実行して、元のマップから元の最終コールバックを呼び出すようにします。
これが理にかなっているかどうかはわかりませんが、上記で説明したことを達成する方法はありますか?
こんにちは@ parky128 、質問ありがとう
iteratee
をreflect
ラップしても機能しますか? reflect
常に結果オブジェクトをcallback
に渡すため、 iteratee
関数のエラーの1つが発生した場合でも、 map
は終了します。 次に、 map
からresults
オブジェクトを繰り返し処理し、 error
プロパティを持つオブジェクトを確認して、それに応じて処理することができます。 map
が取得していない可能性のあるアイテムを再処理する必要はありません。
async.map(coll, async.reflect(function(val, callback) {
// your request code
}, function(err, results) {
// err will always be null now
results.forEach(function(result, i) {
if (result.error) {
// your code for handling errors
// if `coll` is an array, you could access the value that caused
// this error through `coll[i]` as `map` preserves the order for arrays
} else {
// otherwise `result.value` will contain the result of that `iteratee` call
}
});
});
それ以外の場合、質問に答えるために、 map
常にarray
返します。 その配列を反復処理して、どの値がundefined
かを確認できます。 これらは、エラーが発生したか、 undefined
がcallback
に渡されたか、 error
が発生したときに進行中であったか、開始されなかったアイテムに対応します。 reflect
アプローチはおそらくより安全なオプションですが、 undefined
はiteratee
呼び出しからの有効な結果である可能性があるためです。
潜在的な解決策を提供するために時間を割いていただきありがとうございます。 実際には、 iteratee
関数のいずれかが、キャッチしようとしている特定のエラーケースでエラーが発生するとすぐに、async.mapの最終コールバックが呼び出されるようにします。
ドキュメントを見ると、iterateeコールバック関数にエラーを渡すことでこれを達成できることがわかりますが、async.mapが呼び出す最後のコールバックで、その結果オブジェクトを使用して元のオブジェクトと比較できるかどうか疑問に思っていますコレクションを作成し、処理する必要があるものを確認します。
興味のあるエラーケースが返されるとすぐに、async.mapが他のリクエストの処理を試みたくありません。
興味のあるエラーケースが返されるとすぐに、async.mapが他のリクエストの処理を試みたくありません。
iteratee
が非同期であるとすると、 async.map
は、最後のコールバックが呼び出されたときにすべてのアイテムの処理を開始します。 結果オブジェクトをコレクションと比較して、まだ処理が完了していないアイテムを確認できる可能性がありますが、それには落とし穴もあります。 たとえば、結果オブジェクトはiteratee
の解決時に更新されるため、同期的に実行する必要があります。同じティックで、最後のコールバックが呼び出されます。
mapSeries
試すことができます。 mapSeries
は、一度に1つのリクエストのみを実行します。 つまり、現在のアイテムが処理を終了したときにのみ次のアイテムを呼び出します(すべてを一度に開始するのではありません)。 これは、エラーが発生し、最後のコールバックが呼び出されると、 iteratee
が実行されなくなることを意味します。 次に、結果をコレクションと比較して、まだ処理されていないアイテムを確認できます。 これはまだ少し回避策ですが、 async.map
を使用するよりも優れています。 ただし、このアプローチの主な欠点は、リクエストが並行して処理されなくなることです。
たとえば、コレクションが配列の場合
async.mapSeries(coll, function(val, callback) {
// your iteratee function
}, function(err, results) {
if (err) {
// unprocessItems will include the item that errored.
var unprocessItems = coll.slice(results.length - 1);
// handle the unprocessedItems
}
});
うーん、はい、私のiteratee関数は、リクエストライブラリを使用して発信httpリクエストを作成し、その結果をコールバックするため、非同期です。 したがって、反復するアイテムが10個あるとすると、4個が成功し、5個目が失敗し、エラーパラメータを指定してiteratee関数へのコールバックを呼び出します。つまり、async.mapへの最後のコールバックの結果オブジェクトには4つの成功した結果?
もしそうなら、今のところ私はそれがまだすべての発信呼び出しを行うという事実で生きます。 将来的には、配列を小さな配列に分割し、mapSeries内で小さなasync.mapsを実行して、リクエストがヒットしているターゲットサーバーへの最初のヒットを最小限に抑えることができます。
@hargasinski - async.reflect
アプローチを使用することになりましたが、これはうまく機能しており、エラーが発生したすべてのアイテムを完全に表示できます:+1:
ありがとう!
最も参考になるコメント
こんにちは@ parky128 、質問ありがとう
iteratee
をreflect
ラップしても機能しますか?reflect
常に結果オブジェクトをcallback
に渡すため、iteratee
関数のエラーの1つが発生した場合でも、map
は終了します。 次に、map
からresults
オブジェクトを繰り返し処理し、error
プロパティを持つオブジェクトを確認して、それに応じて処理することができます。map
が取得していない可能性のあるアイテムを再処理する必要はありません。それ以外の場合、質問に答えるために、
map
常にarray
返します。 その配列を反復処理して、どの値がundefined
かを確認できます。 これらは、エラーが発生したか、undefined
がcallback
に渡されたか、error
が発生したときに進行中であったか、開始されなかったアイテムに対応します。reflect
アプローチはおそらくより安全なオプションですが、undefined
はiteratee
呼び出しからの有効な結果である可能性があるためです。