while(count!==3) 无法检查回调状态

while(count!==3) fail to check callback state

我是通过 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 语句,它显示计数始终为 0。
然后我偷看了答案,了解到一种解决方法是检查 response.on("end", ...) 回调中的计数值,如下所示:

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-loop方法没有成功我仍然很困惑
在此先感谢所有查看此内容的人。

JavaScript 是单线程的。它执行每个执行上下文直到它完成,然后它检查事件循环以查看是否有任何新的执行上下文排队等待它应该执行(例如异步函数的回调)。

三个getData立即调用所有return,然后while循环在线程中执行。 http.get 的回调在当前执行上下文完成之前无法执行(直到 while 循环及其之后的所有内容都已执行),因此计数无法增加,循环也无法结束。

您找到的解决方案运行良好,但为了帮助理解,您应该认识到 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 毫秒任意检查一次,而不是等到第三个回调执行然后立即记录结果。它只是演示如何 "loop" 不阻塞线程。