learnyounode#9杂耍asynchronous

我正在尝试通过nodechool的learnyounode。

这个问题和前面的问题(HTTP COLLECT)是一样的,你需要使用http.get()。 但是,这次您将获得三个URL作为前三个命令行参数。

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

我很困惑,为什么我的解决scheme无法正常工作,因为它看起来一样,但function更强大,我不确定它们的内部testing工作:

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

官方解决scheme

 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) 

基本上第一个testing永远不会通过(虽然如果在迭代数组中只有一个url(而不是3),那么第一个testing通过,而不是其他testing)。 任何见解都会很棒。 我不知道在哪里问这个,也许我只是缺less一些JS的东西,所以很抱歉,如果这是不合适的。

你还没有确定所有的url都被下载了。

这些请求不一定会按顺序返回。 考虑3是否先回来。 你会跳过其他两个url,只打印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); }); } 

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

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

我得到它的工作,而不使用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); 

我是一个初学者,所以也许这个解决scheme有问题,这是使用asynchronous/等待,通过作出承诺的数组,并等待他们解决,这将控制响应的顺序

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