【问题标题】:How to execute http requests strictly one by one in node.js? [closed]node.js中如何严格执行http请求? [关闭]
【发布时间】:2013-12-28 10:38:08
【问题描述】:

所以,我有一个包含一些值的数组。我想将这些值发送到 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 毫秒内发送,然后在收到响应时回调正在侦听。但它不应该!我已将 callback() 放在 http.request(options, callback) 中!!它是怎么发生的?

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

【问题讨论】:

  • “严格一个一个”是什么意思?我认为这意味着您不想在第一个完成之前开始一个新的-但随后您还写了“尽可能快”-对我而言,这表明您确实想一次将它们全部发送,因为这将尽可能快。您能否编辑/澄清您的代码未按预期工作的方式。
  • 你得到了我想要的“严格一个一个”的意思。 “尽可能快”意味着不使用 setTimeout() 或类似的东西。但你是对的,我最好从帖子中删除“尽可能快”的东西

标签: javascript node.js stack


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

【讨论】:

  • 好吧,问题是我的回调在收到响应时被调用 not,但要早得多(我用 console.logging 它测量接收响应的时间 - 是这对吗?)以及如何在请求完成时进行回调?我在docs 中没有找到任何东西
  • callback() 在收到数据时被调用,这是你的实现不正确。看我的回答。
【解决方案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 all in correct order:

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);

【讨论】:

    【解决方案3】:

    你可以试试这样的:

    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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 2018-06-02
      • 2017-06-30
      • 2011-07-29
      • 1970-01-01
      相关资源
      最近更新 更多