2017-04-18 5 views
-1

私はforEach()ループを使用してARRAYを実行しています。 すべての要素について、要求を呼び出す必要があります。 呼び出されたすべてのリクエストが完了した後にnext()を呼び出したいとします(呼び出すリクエストが少なくとも100件あると仮定します)。NODE.JS - 複数のREQUESTSを実行した後、next()を正しく呼び出す方法は?

これにアプローチする方法はありますか?ここで

は私の質問を実証するために少しのサンプルコードである -

var arr = ["A" , "B", "C" , "D" , "E"]; 
 
arr.forEach(function (arrayItem) { 
 
\t var options = { 
 
     method: 'GET', 
 
     url:"some_url", 
 
     headers: {...} 
 
    }; 
 
    request(options, function (error, response, body) 
 
    { 
 
    if (error) {next(error);} 
 

 
    // DO_SOMETHING based on arrayItem 
 

 
    }); // end of request() 
 
}); //end of forEach 
 

 
// WHERE should I place the next()?

答えて

1

あなたがこれを行うことができますカップルの方法があります。 request()へのすべての呼び出しは非同期であり、ループが終了してからしばらく後に終了するので、何とかそれらを追跡する必要があります。プロミスを使用する方法とカウンターを使用する方法の2つの方法を示します。おかげでたくさんのHardik-ジャイナ教、@

約束

// create wrapper function that returns a promise 
function requestPromise(options) { 
    return new Promise(function(resolve, reject) { 
     request(options, function(error, response, body) { 
      if (error) return reject(error); 
      resolve({response: response, body: body}); 
     }); 
    }); 
} 

var arr = ["A" , "B", "C" , "D" , "E"]; 

Promise.all(arr.map(function(item) { 
    // create options object here for each request 
    var options = { 
     method: 'GET', 
     url:"some_url", 
     headers: {...} 
    }; 

    return requestPromise(options); 

})).then(function(results) { 
    // process results here 

    // call next() here because all processing is now done 
    next(); 
}).catch(function(err) { 
    // error happened 
    next(err); 
}); 

マニュアルカウンター

var arr = ["A" , "B", "C" , "D" , "E"]; 
var errDone = false; 
var cntr = 0; 
arr.forEach(function (arrayItem) { 
    var options = { 
     method: 'GET', 
     url:"some_url", 
     headers: {...} 
    }; 
    request(options, function (error, response, body) { 
    if (error) { 
     if (!errDone) { 
      // latch error so we don't call next(error) multiple times 
      errDone = true; 
      next(error); 
     } 
    } else { 
     // process result here 

     // check if this is the last response 
     ++cntr; 
     if (cntr === arr.length) { 
      // all responses done here 
      next(); 
     } 
    } 
    }); 
+0

こんにちは@ jfriend00 - ありがとう、それは本当に私に全く新しいこのコンセプトを理解するのを助けました。 あなたの解決策に関するちょっとしたフォローアップの質問 - catch()メソッドでは、エラーには失敗したリクエストの特定のレスポンスとその詳細がすべて含まれていますか?応答のエラーメッセージ? –

+0

@GadiBenAmram - 最初に失敗した 'request()'の 'error'値が含まれます。必要に応じて、より多くの情報を含む独自のオブジェクトを構築し、 'reject(error)'の代わりに 'reject(yourObj)'を呼び出すだけで、より多くの情報を含めることができます。 – jfriend00

+0

それを得ました! @ jfriend00もう一度ありがとう、それは本当に本当に助けになりました:-)。 –

1

私はこのための約束を使用するためにあなたをお勧めします。

配列内のすべての要素がPromiseになり、すべてが実行された後に.then()関数が呼び出されます。あなたのケースでは

Promise.all()が最善の解決策になります。 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

使用法:

var A = new Promise((resolve, reject) => { 
    var options = { 
     method: 'GET', 
     url:"some_url", 
     headers: {...} 
request(options, function (error, response, body) 
    { 
    if (error) {reject()}; 
    resolve(); 
    }); 
}); 
var B = new Promise((resolve, reject) => { 
    var options = { 
     method: 'GET', 
     url:"some_url", 
     headers: {...} 
request(options, function (error, response, body) 
    { 
    if (error) {reject()}; 
    resolve(); 
    }); 
}); 
var arr = [A , B, C , D , E]; 
Promise.all(arr).then(next()); 
+0

ねえ。 私は大きなアレー(100以上の要素)のマッピングにも役立ちましたので、別の答えをマークすることを選択しましたが、あなたの答えはソリューションへのアプローチ方法を理解するのにも役立ちました。そのような偉大な反応を書く努力をしています。 もう一度おねがいします:-)。 ガディ。 –

+0

うれしかった! :D –

関連する問題