var http = require('http');
var res = ["","",""];
for(i =2;i<5;i++){
http.get(process.argv[i],function(response){
response.setEncoding('utf8');
str = "";
count =i-2;
response.on("data", function(data) {
str = str.concat(data);
});
response.on("end", function() {
res[count] = str;
console.log(count);
console.log(res[count]);
});
});
}
while(true) {
if(res[0]!==""&&res[1]!==""&&res[2]!=="")
{
console.log(res[0]);
console.log(res[1]);
console.log(res[2]);
break;
}
}
我将有三个URL作为前三个命令行参数。我的工作是从每个URL收集数据作为字符串,并按照它们在命令行中出现的顺序将它们打印到控制台。现在代码不会打印任何东西,它会陷入无限循环。有什么问题?
答案 0 :(得分:2)
代码中存在两个问题。首先,你有一个循环变量的闭包,它使得值与你期望的guvinder372解释的不同。另请参阅讨论问题的this answer和this answer,它们演示了使用Function.bind
解决问题的更好方法。
第二个问题是你最后设置while
循环的方式。该循环将持续运行,并且永远不允许http.get
中的回调函数运行。相反,检查回调是否有其他响应进入,一旦所有三个响应进入,打印输出。
for(i =2;i<5;i++){
http.get(process.argv[i],function(response){
response.setEncoding('utf8');
str = "";
count =i-2;
response.on("data", function(data) {
str = str.concat(data);
});
response.on("end", function() {
//Check here if responses are in
if(res[0]!==""&&res[1]!==""&&res[2]!=="") {
}
res[count] = str;
console.log(count);
console.log(res[count]);
});
});
}
答案 1 :(得分:0)
问题 - 当调用回调处理程序时,i的值已经达到5,并且对于所有回调处理程序执行它将保持为5。
您需要重构代码以将i的值传递给该调用方法
var http = require('http');
var res = ["","",""];
for(i =2;i<5;i++)
{
callBackDefiner(i)
}
function callBackDefiner( i )
{
http.get(process.argv[i],function(response){
response.setEncoding('utf8');
str = "";
count =i-2;
response.on("data", function(data) {
str = str.concat(data);
});
response.on("end", function() {
res[count] = str;
console.log(count);
console.log(res[count]);
});
});
}
答案 2 :(得分:0)
您无法在for...loop
周期内执行多个http请求,而无需等待响应。
要以现代方式编写此代码,您需要一些新的构造/模式,例如Promise
。然后,您可以等待每个响应,收集响应并退出呼叫者。
举个例子,看看我的javascript客户端解决方案。这也适用于Node.js
中的一小部分工作,您只需更改块函数ExecutionBlock
中执行请求的方式。
假设我们想要发送到一些url /或不同url的数组的参数数组,我们将使用Promise.all
构造运行。
在以下代码段中尝试一下。
要了解如何将此解决方案应用于Node.js
,请参阅http
获取和发布here的实现,并在本文后面看到,以便在异步任务的节点中执行更复杂的操作。 / p>
var console = {
log: function(s) {
document.getElementById("console").innerHTML += s + "<br/>"
}
}
// Simple XMLHttpRequest
// based on https://davidwalsh.name/xmlhttprequest
SimpleRequest = {
call: function(what, response) {
var request;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {}
}
}
// state changes
request.onreadystatechange = function() {
if (request.readyState === 4) { // done
if (request.status === 200) { // complete
response(request.responseText)
} else response();
}
}
request.open('GET', what, true);
request.send(null);
}
}
//PromiseAll
var promiseAll = function(items, block) {
var self = this;
var promises = [],
index = 0;
items.forEach(function(item) {
promises.push(function(item, i) {
return new Promise(function(resolve, reject) {
if (block) {
block.apply(this, [item, index, resolve, reject]);
}
});
}(item, ++index))
});
return Promise.all(promises)
}; //promiseAll
// LP: deferred execution block
var ExecutionBlock = function(item, index, resolve, reject) {
SimpleRequest.call('https://icanhazip.com/', function(result) {
if (result) {
console.log("Response[" + index + "] " + result);
resolve(result);
} else {
reject(new Error("call error"));
}
})
}
arr = [1, 2, 3]
promiseAll(arr, (item, index, resolve, reject) => {
console.log("Making request [" + index + "]")
ExecutionBlock(item, index, resolve, reject);
})
.then((results) => { console.log(results) })
.catch((error) => { console.error(error) });
&#13;
<div id="console" />
&#13;
对于应用于node.js的Promise
和Promise.all
的类似方法,请参阅我的问题here。这是关于以异步方式在节点中生成泛型进程的执行。
更复杂的示例here显示了如何使用N * M
在http.get
Promise
执行程序中生成和链接多个级别的http调用。因此,您将执行N
个请求,每个请求都会启动M
个请求,并且感谢Promise.all
您将等待每个请求,等待第一个M
的所有结果然后是N * M
请求响应数组的所有结果。