【问题标题】:learnyounode #9 juggling asynclearnyounode #9 杂耍异步
【发布时间】:2015-04-06 03:37:16
【问题描述】:

我正在尝试通过 nodeschool 的 learnyounode。

这个问题和上一个问题(HTTP COLLECT)一样 你需要使用 http.get()。然而,这一次你将 提供三个 URL 作为前三个命令行参数。

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

我很困惑为什么我的解决方案不能完全正常工作,因为它对我来说看起来一样,但功能更强大,并且不确定它们的内部测试工作原理:

1.  ACTUAL:    ""
1.  EXPECTED:  "As busy as a dead horse also lets get some dero. Built like a sleepout no dramas lets get some chook. She'll be right thingo my she'll be right ute. "

2.  ACTUAL:    "She'll be right bizzo no worries she'll be right fair dinkum. We're going aerial pingpong no worries as busy as a gyno. "
2.  EXPECTED:  "She'll be right bizzo no worries she'll be right fair dinkum. We're going aerial pingpong no worries as busy as a gyno. "

3.  ACTUAL:    "He's got a massive pretty spiffy heaps she'll be right brizzie. He hasn't got a fly wire where shazza got us some strewth. She'll be right spit the dummy with it'll be fair go. We're going gobsmacked with as stands out like arvo. He's got a massive bush bash mate she'll be right slacker. "
3.  EXPECTED:  "He's got a massive pretty spiffy heaps she'll be right brizzie. He hasn't got a fly wire where shazza got us some strewth. She'll be right spit the dummy with it'll be fair go. We're going gobsmacked with as stands out like arvo. He's got a massive bush bash mate she'll be right slacker. "

4.  ACTUAL:    ""
4.  EXPECTED:  ""

我的代码:

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

var result = [];
var urls = process.argv.slice(2);
urls.forEach(function(url, i) {
  http.get(url, function(response) {
    response.pipe(bl(function(err, data) {
      if (err) return console.error(err);
      result[i] = data.toString();
      if (i === urls.length - 1) {
        console.log(result.join('\n'));
      }
    }));
  });
});

官方解决方案:

var http = require('http')
var bl = require('bl')
var results = []
var count = 0

function printResults () {
  for (var i = 0; i < 3; i++)
    console.log(results[i])
}

function httpGet (index) {
  http.get(process.argv[2 + index], function (response) {
    response.pipe(bl(function (err, data) {
      if (err)
        return console.error(err)

      results[index] = data.toString()
      count++

      if (count == 3)
        printResults()
    }))
  })
}

for (var i = 0; i < 3; i++)
  httpGet(i)

基本上第一个测试永远不会通过(尽管如果迭代数组中只有 1 个 url(而不是 3 个),则第一个测试通过但其他测试不通过)。任何见解都会很棒。我不知道在哪里问这个问题,也许我只是错过了一些 JS 的东西,如果这不合适,很抱歉。

【问题讨论】:

  • 当您异步进行下载时,您也在尝试异步打印它们。只有在知道下载已完成后,您才应该进行打印。正如@mrmcgreg 指出的那样,演示代码一直等到计数达到 3,然后才决定打印结果。他们所做的最大区别在于,它们仅在将 data 分配给结果后才增加计数。

标签: javascript node.js


【解决方案1】:

您尚未确定所有网址都已下载。

请求不一定按顺序返回。考虑是否 3 先回来。您将跳过其他两个 url,只打印出 3 个。

演示代码计算响应的数量,因此可以保证在打印出答案之前得到所有内容。

【讨论】:

  • 谢谢!我错过了这一点,我全神贯注于在我的 arr 中以正确的顺序获取响应,而不考虑它们是否完成下载。我将我的 console.log 编辑为 if (result.filter(function(res) { return res !== undefined; }).length === urls.length) { //log results when all urls have returned responses console.log(result.join('\n')); }
  • 虽然转念一想,用 int 计数可能更好:)
【解决方案2】:

我认为您只需要等到所有请求的结果结束或任何一个错误。有我通过的答案:

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

var urls = process.argv.slice(2)
var count = urls.length;

var results = [];

urls.forEach((url, index) => {
    http.get(url, (res) => {
        res.pipe(bl((err, data) => {
            if (err) throw err;

            results[index] = data.toString();
            count--;

            if (count == 0) {
                results.forEach((result) => {
                    console.log(result)
                });
            }
        }))
    })
})

【讨论】:

    【解决方案3】:
    var http = require('http');
    
    var links = [2, 3, 4];
    
    var buffer = [];
    
    (function render(index) {
    
    http.get(process.argv[links[index]], function (response){
    
        response.setEncoding('utf8');
    
        response.on('data', function(chunk){
            if(buffer[index] === undefined) {
                buffer[index] = '';
            }
            buffer[index] += chunk;
        });
        response.on('end', function () {
            var newIndex = index+1;
            if(links[newIndex] !== undefined) {
                render(newIndex);
            } else {
                return renderOutput();
            }
        });
        response.on('error', console.error);
    
    }).on('error', console.error);
    })(0); //self-calling function
    
    function renderOutput() {
    
    buffer.forEach(function (elem) {
    
    console.log(elem);
    
    });
    }
    

    【讨论】:

      【解决方案4】:

      我在不使用 bufferList(bl) 模块的情况下让它工作,可能是更通用的方法。

              var http = require('http');
              var urlList = [];
              urlList.push(process.argv[2]);
              urlList.push(process.argv[3]);
              urlList.push(process.argv[4]);
              var results = []
              var count = 0
      
              function getURLdata (index) {
                  http.get(urlList[index], function(response){
                      var data = {};
                      data[index] = '';      
                      response.setEncoding('utf-8');
                      response.on('error', function(err){
                          console.log(err);
                      });
                      response.on('data', function(chunk){
                          data[index] += chunk;
                      });
      
      
                      response.on('end', function(){
                          results[index] = data;
                          count++;
                          if (count == urlList.length){
                              for (var i = 0; i < urlList.length; i++){
                                  console.log(results[i][i]);
                              } 
                          }
                      });
      
                  });
              }
      
              for (var i = 0; i < urlList.length; i++)
                  getURLdata(i);
      

      【讨论】:

        【解决方案5】:

        我是初学者,所以这个解决方案可能有问题,这是使用 async/await,通过做出一系列承诺并等待它们解决,这将控制响应的顺序

        const axios = require("axios")
        const  getURL = async url =>
        {
          let res = await axios.get(url)
          return res.data
        }
        
        const getUrlArray = () => 
        {
          let args = process.argv.slice(2)
          .map(e => getURL(e))
          return Promise.all(args)
        }
        
        getUrlArray()
        .then(data => data.forEach(e => console.log(e)))
        

        【讨论】:

          【解决方案6】:

          非常简单的解决方案,但可以完成工作:

          const http = require('http');
          const bl = require('bl');
          var x; 
          
          for (x = 2; x < 5; x++) {
            http.get(process.argv[x], function (res) {
              res.pipe(bl(function (err, data) {
                if (err) { return console.error(err) }
                console.log(data.toString());
              }));
            });
          };
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-02-23
            • 1970-01-01
            • 2014-11-26
            • 2015-10-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多