2

nodejsアプリに複数のHTTPリクエストがあり、それぞれが文の単語を返します。返信が来るタイミングがバラバラなので、元の文の単語索引をキーにして辞書に保存しています。問題は、リクエスト オブジェクトにアクセスすると、最後のオブジェクトしか取得できないことです。

var completed_requests = 0; 
sentence = req.query.sentence;
sentence = "sentence to be translated"
responses=[];
words = sentence.split(" ");
for(j=0;j<words.length;j++){
    var word = words[j];
    var data={
        word:word
    };
    var options = {
      url: 'example.com',
      form:data,
      index:j
    };
    request.post(options, function(err,httpResponse,body){
        options = options;
        if(!err){
            responses.push({options.index: body});
            completed_requests+=1;
            if(completed_requests==words.length){
                var a="";
                for(var k=0;k<words.length;k++){
                    a+=responses[k]+" ";
                }
                res.render('pages/index', { something: a });
            }
        }
        else{
            //err
        }
    });
}

基本的に、object.indexオブジェクトにアクセスすると、返されるオブジェクトは元のリクエストに使用されたものではなく、最後のものです (何らかの理由で)。これをどのように解決すればよいですか?

4

2 に答える 2

2

Node.js の非同期性により、コードが JavaScript によってどのように評価されるかを見ると、問題が明らかになります。

  1. 最初の単語でループfor(j=0;j<words.length;j++){が実行されます。
  2. の値jが に割り当てられoptions.indexます。ループ実行の場合、これoptions.indexの値は になります0
  3. request.post(options, function(err,httpResponse,body){が実行されますが、コールバック ハンドラは後で呼び出されます。
  4. 最初の単語でループfor(j=0;j<words.length;j++){が実行されます。
  5. の値jが に割り当てられoptions.indexます。options.indexの値が になりました1
  6. request.post(options, function(err,httpResponse,body){が実行されますが、コールバック ハンドラは後で呼び出されます。

options新しいオブジェクトは作成されませんが、ループの実行ごとに の値jが割り当てられるため、問題が明らかになります。options.index最初のコールバック ハンドラが呼び出されたときoptions.indexの値は ですwords.length - 1

この問題を解決するために、オプション オブジェクトの作成を関数でラップします。executeRequest

var completed_requests = 0; 
sentence = req.query.sentence;
sentence = "sentence to be translated"
responses=[];
words = sentence.split(" ");
for(j=0;j<words.length;j++){
    var word = words[j];
    var data={
        word:word
    };

    function executeRequest(url, form, index) {
        var options = {
            url: url,
            form: form,
            index: index
          };
          request.post(options, function(err,httpResponse,body){
              // options = options; Superfluous
              if(!err){
                  responses.push({ [index]: body});
                  completed_requests+=1;
                  if(completed_requests==words.length){
                      var a="";
                      for(var k=0;k<words.length;k++){
                          a+=responses[k]+" ";
                      }
                      res.render('pages/index', { something: a });
                  }
              }
              else{
                  //err
              }
          });
    }

    executeRequest('example.com', data, j);
}

JavaScript でのスコーピングとホイストについての良い読み物は、http: //www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html にあります。

于 2016-01-28T10:34:00.327 に答える
0

forEach や map などの非同期ルーチンを使用する必要があります。また、io のコールバックを処理する方法を理解するために、node の非同期の性質について読んでおくことをお勧めします。

于 2016-01-27T15:48:37.053 に答える