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.indexoptions.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 之类的异步例程,另外我建议您阅读 node 的异步性质以帮助了解如何处理 io 的回调。

于 2016-01-27T15:48:37.053 回答