如何在node.js中严格执行http请求?

时间:2013-12-28 10:38:08

标签: javascript node.js stack

所以,我有一些值的数组。我想将这些值发送到www.example.com。我必须每个请求只发送一个值。

我在node.js中使用http.request这个任务:

var myArr = [1,2,3,4,5,6,7,8,9,10,11,12];

function requestSender(data, callback)
  {
      var post = querystring.stringify({
        data: data
      });

      var options = {
        hostname: 'www.example.com',
        port: 80,
        path: '/upload',
        method: 'POST'
      };

      var req = https.request(options, function(res)
      {
        res.setEncoding('utf-8');
        res.on('data', function(data)
        {
          callback();
        });
      });

      req.on('error', function(e) {
        console.log('problem with request: ' + e.message);
      });
      req.write(post);
      req.end();
  }

要逐个发送请求我正在使用函数,它接受一个函数数组并递归地添加下一个函数作为回调函数:

function stack(arr)
{
  var newArr = arr.slice(1);
  arr[0](function()
    {
      if (typeof newArr[0] == 'function') stack(newArr);
    });
}

要将所有这些人员编成一个,我使用以下代码:

var functionsArr = [];
for (i in myArr)
{
  functionsArr.push(function(callback)
    {
      var value = myArr[i];
      requestSender(value, callback);
    }); 
};

stack(functionsArr);

但实际上,这不起作用:所有请求都在1毫秒内发送,然后在回复响应时回调。但它不应该!我在http.request中放了 callback()(选项,回调)!!它是如何发生的?

所以我的问题是: 1)如何在node.js中严格逐个发送http请求? 2)为什么我的解决方案不起作用?

3 个答案:

答案 0 :(得分:3)

  1. 查看async库,特别是mapSeries方法。
  2. 收到数据时会调用您的回调,而不是在请求完成时调用。

答案 1 :(得分:2)

我看到我迟到了,但无论如何:

将函数放入循环或递归时,闭包中的变量在执行函数时计算,而不是在创建函数时计算。所以

for (i in [1, 2, 3]) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}

返回

3
3
3

for (i in [1, 2, 3]) {
    setTimeout(function(i) {
        return function() {
            console.log(i);
        };
    }(i), 1000);
}

会正确地给你

1
2
3

这就是为什么通常不建议将函数定义放在循环中。

无论如何,这里有更正的代码,请注意它console.logs所有内容的顺序正确:

var http = require('http');
var querystring = require('querystring');

var myArr = [1,2,3,4,5,6,7,8,9,10,11,12];

function requestSender(d, callback)
{
  var post = querystring.stringify({
    data: d
  });

  var options = {
    hostname: 'www.example.com',
    port: 80,
    path: '/upload',
    method: 'POST'
  };

  var req = http.request(options, function(res)
  {
    res.setEncoding('utf-8');
    res.on('data', function(data)
    {
      console.log(d);
      console.log(data);
      callback();
    });
  });

  req.on('error', function(e) {
    console.log('problem with request: ' + e.message);
  });
  req.write(post);
  req.end();
}

function stack(arr)
{
  var newArr = arr.slice(1);
  arr[0](function(arg) {
    return function() {
      if (arg.length > 0)
        stack(arg);
    };
  }(newArr));
}

var functionsArr = [];
for (i in myArr)
{
  functionsArr.push(function(i) {
    return function(callback) {
      var value = myArr[i];
      requestSender(value, callback);
    };
  }(i));
}

stack(functionsArr);

答案 2 :(得分:0)

您可以尝试这样的事情:

var myArr = [1,2,3,4,5,6,7,8,9,10,11,12];
var counter = -1;

function function requestSender(data)
{
    var post = querystring.stringify({ data: data });
    var options =
    {
        hostname: 'www.example.com',
        port: 80,
        path: '/upload',
        method: 'POST'
    };

    var req = https.request(options, sendNextData);

    req.on('error', function(e) 
    {
        console.log('problem with request: ' + e.message);
    });
    req.write(post);
    req.end();
}

function sendNextData()
{
    if(++counter < myArr.length)
    {
        requestSender( myArr[ counter ] );
    }
}
sendNextData();