【问题标题】:node.js stream pipe asynchronous or synchronousnode.js 流管道异步或同步
【发布时间】:2014-12-05 12:06:08
【问题描述】:

问题:这是 node.js 的 learnyounode 模块 JugglingAsync 中的问题。 "这个问题和上一个问题 (HTTP COLLECT) 一样,需要使用 http.get()。不过,这次会提供三个 URL 作为前三个命令行参数。

您必须收集每个 URL 提供给您的完整内容并将其打印到控制台 (stdout)。您不需要打印出长度,只需将数据作为字符串;每个 URL 一行。问题是您必须以与作为命令提供给您的 URL 相同的顺序打印它们 行参数。”

我尝试使用 node.js stream.readable 类将响应从第一个 URL 传递到第二个,并将响应从该 URL 传递到第三个。我期待这将同步运行,即当第一个请求完成时,第二个请求将通过管道传输。我正在使用包 bl (https://www.npmjs.org/package/bl) 来收集获取请求的所有响应数据。 下面的代码片段:

var https = require('http');
var bl = require('bl');
var finalString = '';

https.get( process.argv[2], function(response)
    {
        response.setEncoding('utf8');
        response.pipe(bl(function (err, data)
        {
            console.log("First request called");
            if (err) return console.error(err);
            console.log(data.toString());

        })).pipe(bl(function(err, data)
        {

            console.log("Second Request called");
            https.get (process.argv[3], function( response)
            {
                response.setEncoding('utf8');
                response.pipe(bl( function (err, data)
                {
                    if (err) return console.error(err);                    
                    console.log(data.toString());

                }))
            }).on('error', function(err)
                {
                    console.log(err);
                })
        })).pipe( bl(function(err,data)
            {
                console.log("Third request called");
                https.get (process.argv[4], function( response)
                {

                    response.setEncoding('utf8');
                    response.pipe(bl( function (err, data)
                    {
                        if (err) return console.error(err);                        
                        console.log(data.toString());

                    }))

                }).on('error', function(err)
                    {
                        console.log(err);
                    })
            })
            )
    }).on('error', function (err)
    {
            console.log(err);
    }
);

输出不遵循请求的顺序。我做错了什么?

【问题讨论】:

    标签: javascript node.js


    【解决方案1】:

    据我所知,Streams {in nodejs} 中的pipe 是异步的,但我在某处读过它们也可以充当同步的。您上面的解决方案以异步方式运行,因此以随机顺序打印数据。

    您的解决方案可以按如下方式进行:-

    var https = require('http');
    var bl = require('bl');
    var finalData = [];
    var count = 0;
    
    https.get( process.argv[2], function(response)
        {
            response.setEncoding('utf8');
            response.pipe(bl(function (err, data)
            {
                // console.log("First request called");
                if (err) return console.error(err);
                finalData[0] = data.toString();
                count++;
                printThemOut(count);
    
            })).pipe(bl(function(err, data)
            {
    
                // console.log("Second Request called");
                https.get (process.argv[3], function( response)
                {
                    response.setEncoding('utf8');
                    response.pipe(bl( function (err, data)
                    {
                        if (err) return console.error(err);
                        finalData[1] = data.toString();
                        count++;
                        printThemOut(count);
    
                    }))
                }).on('error', function(err)
                    {
                        console.log(err);
                    })
            })).pipe( bl(function(err,data)
                {
                    // console.log("Third request called");
                    https.get (process.argv[4], function( response)
                    {
    
                        response.setEncoding('utf8');
                        response.pipe(bl( function (err, data)
                        {
                            if (err) return console.error(err);
                            finalData[2] = data.toString();
                            count++;
                            printThemOut(count);
                        }))
    
                    }).on('error', function(err)
                        {
                            console.log(err);
                        })
                })
                )
        }).on('error', function (err)
        {
                console.log(err);
        }
    
    
    
    );
    
    function printThemOut(count) {
      if (count == 3) {
        for (var i = 0; i < finalData.length; i++) {
          console.log(finalData[i]);
        }
      }
    }
    

    上述解决方案有效,但问题是(在我的情况下),第一个 URL 调用的第一个数据,第一个单词丢失了。

    {我认为这是因为在第一个 URL 的相同数据上使用多个管道}

    说明

    我们需要一个计数器来索引http.get() 获取的数据,以便第一个 URL 数据存储在索引 0 和第二个索引 1 中,依此类推。这有助于同步所有异步数据...

    适当的解决方案

    正确的解决方案是循环调用并在每个数据上使用单个管道...

    var http  = require("http");
    var bl    = require("bl");
    
    var completeData = [];
    var count = 0;
    for (var i = 2; i < process.argv.length; i++) {
      (function(index){
        http.get(process.argv[index], function(res) {
          res.pipe(bl(function(err, data) {
            if (err) {
              return console.log(err);
            }
            // console.log(index);
            completeData[index-2] = data.toString();
            count++;
            // console.log("Data: " + data.toString());
            if (count === process.argv.length-2) {
              printThemOut(completeData);
            }
          }))
        })
      })(i);
    }
    
    function printThemOut(data) {
      for (var i = 0; i < data.length; i++) {
        console.log(data[i]);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-07-11
      • 2013-05-11
      • 1970-01-01
      • 2015-02-23
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 2015-12-19
      • 2023-03-29
      相关资源
      最近更新 更多