我正在使用NodeSchool中名为learnyounode的教程学习Node。这是它提供的13个问题中的一个:向前3个命令行参数指示的3个URL发送3个http get请求,在收集到所有响应块时按照URL的顺序打印响应。
我想出了这段代码:
var http = require("http");
var count = 0;
var strArr = ["","",""];
getData(0);
getData(1);
getData(2);
while(count!==3);
console.log(strArr[0]);
console.log(strArr[1]);
console.log(strArr[2]);
function getData(i) {
http.get(process.argv[i+2], function (response) {
response.setEncoding("utf8");
response.on("data", function (data) {
strArr[i] += data;
});
response.on("end", function (data) {
count++;
});
});
}
我期待while循环阻止我的打印语句直到计数变为3,即所有3个响应都被完全收集。然而,它没有像我预期的那样工作。另外,我在while循环中放了一个print语句,它表明count总是为0
然后我偷看了答案,并了解到一种方法是检查response.on("end", ...)
的回调中的count值,如下所示:
var http = require("http");
var count = 0;
var strArr = ["","",""];
getData(0);
getData(1);
getData(2);
function getData(i) {
http.get(process.argv[i+2], function (response) {
response.setEncoding("utf8");
response.on("data", function (data) {
strArr[i] += data;
});
response.on("end", function (data) {
count++;
if(count===3) {
console.log(strArr[0]);
console.log(strArr[1]);
console.log(strArr[2]);
}
});
});
}
这样,我确实通过了测试,但是为什么while循环方法没有成功仍然困扰着我。
提前感谢任何看过这个的人。
答案 0 :(得分:2)
JavaScript是单线程的。它执行每个执行上下文直到它完成,然后它检查事件循环以查看是否有任何新的执行上下文排队它应该执行(例如异步函数的回调)。
三个getData
调用都立即返回,然后while循环在线程中执行。 http.get
的回调在当前执行上下文完成之前无法执行(直到while循环及其执行后的所有内容),因此无法计数增加,也无法循环结束。 / p>
您找到的解决方案效果很好,但为了帮助理解您应该意识到setTimeout和setInterval是异步的,因此它们不会阻塞该线程。你可以通过以下方式解决这个问题:
getData(0);
getData(1);
getData(2);
setTimeout( function check_count ( ) {
if ( count !== 3 )
return setTimeout( check_count, 100 );
console.log(strArr[0]);
console.log(strArr[1]);
console.log(strArr[2]);
}, 100 );
这不是一个好的解决方案,因为它是每100毫秒任意检查,而不是只等到第三个回调执行,然后立即记录结果。这只是一个展示你如何能够循环和#34;没有阻止线程。