在nodejs循环中发出http请求

时间:2016-04-29 08:18:15

标签: node.js loops httprequest nonblocking

发现几乎不可能将循环中的http请求的响应捕获为数组。我可以在console.log中看到该数组,但是当我将数组传递给http服务器的响应时,我得到一个空白数组。我做错了什么,或者有更好的方法来做到这一点?

代码:

router.route('/uprns').post(function(request, response){
  response.setHeader('content-type', 'application/text');

  console.log('first element from the array is '+request.body.UPRNS[0]);
  console.log('Number of items in array is '+request.body.UPRNS.length);

if (request.body.UPRNS.length == 0) {
         response.send( 'no UPRNS in request' );
    }

  var output = [];
  var obj = '';

  for( var i = 0; i < request.body.UPRNS.length; i++) {

    obj = request.body.UPRNS[i];

    //Make  HTTP calls to     
    var options = {
      host: 'orbisdigital.azure-api.net',
      path: '/nosecurity/addresses?uprn='+obj // full URL as path
    };

    callback = function(res) {    
      res.on('data', function (chunk) {
        output.push(chunk.toString());
      });

      //the whole response has been recieved
      res.on('end', function () {
        console.log(output);
      });
    }

    Https.request(options, callback).end();
  }

  response.send(output);

}); 

我知道在for循环中有很多关于阻塞进程的讨论,但是没有明确的推荐方法来处理循环中的http调用。 谢谢 。

2 个答案:

答案 0 :(得分:0)

这是代码。请参阅添加注释的代码。使用node.js here's a starter阅读异步编程。

router.route( '/uprns' ).post( function ( request, response ) {
    response.setHeader( 'content-type', 'application/text' );
    console.log( 'first element from the array is ' + request.body.UPRNS[ 0 ] ); // your  1st element in  JSON array.

    console.log( 'Number of items in array is ' + request.body.UPRNS.length );
    var output = [];
    var obj = '';

    for ( var i = 0; i < request.body.UPRNS.length; i++ ) {

        obj = request.body.UPRNS[ i ];

        console.log( obj );

        //Make  HTTP calls to

        var options = {
            host: 'orbisdigital.azure-api.net',
            path: '/nosecurity/addresses?uprn=' + obj // full URL as path
        };

        Https.request( options, callback ).end();

    }

    var countResponses = 0;
    // Don't make functions in a loop, so I moved this function down
    // here.
    function callback( res ) {

        res.on( 'data', function ( chunk ) {
            output.push( chunk.toString() );
        });

        // Handles an error
        request.on('error', function(err) {
          console.error(err.stack);
          response.statusCode = 500; // or what ever.
          response.send(500, 'there was an error');
        });

        //the whole response has been recieved
        res.on( 'end', function () {
            console.log( output );
            countResponses++;
            if (countResponses === request.body.UPRNS.length) {

                // Previously this code was executed directly 
                // after the loop finished.  It did not wait for
                // all the responses, so it sent the empty response.
                // However, the other console.log(output) statements
                // were called after this.
                //
                // There is a bug here that if request.body.UPRNS.length
                // is zero, then the user will never get a response.  I 
                // let you fix this up :).
                response.send( output );
            }
        } );

    }

} );

答案 1 :(得分:0)

处理此类场景的更好方法是使用async.js而不是for循环。 https://github.com/caolan/async