0

The goal of the following code is to fetch webpages from three sites specified on command line and to display them in the order specified on command line. My first solution (shown below) was to use while loop to wait for three async tasks to finish but the while loop keeps looping forever. I learned that the correct solution was to detect if variable "count" reached 3 inside each async task (also shown below but commented out), not outside async task. But I'm wondering why my initial solution does not work. Can someone point me to the right Javascript specification of something that explains the flaw of my initial solution? Thanks!

var http = require('http');
var bl = require('bl');
var url1 = process.argv[2];
var url2 = process.argv[3];
var url3 = process.argv[4];
var content1;
var content2;
var content3;
var count = 0;

http.get(url1, function (res) {
        res.pipe(bl(function (err, data) {
                content1 = data.toString();
                count++;
//              if (count == 3) printAll();
        }));
});

http.get(url2, function (res) {
        res.pipe(bl(function (err, data) {
                content2 = data.toString();
                count++;
//              if (count == 3) printAll();
        }));
});

http.get(url3, function (res) {
        res.pipe(bl(function (err, data) {
                content3 = data.toString();
                count++;
//              if (count == 3) printAll();
        }));
});


function printAll() {
        console.log(content1);
        console.log(content2);
        console.log(content3);
}

// this while loop loops forever
while (count < 3) {
  console.log('waiting..');
};

printAll();
6
  • 6
    setTimeout() is asynchronous too. It doesn't pause the loop. Commented May 25, 2016 at 15:19
  • Good to know, thanks. But my question still remains. Commented May 25, 2016 at 15:21
  • setTimeout will not wait a second there. It will simply try to call null in one seconds time repeatedly, which is BAD. If you're going to do anything, then call something another function and use setTimeout there to continue checking using an if statement instead of a while. You should be using a callback though from an async function. Commented May 25, 2016 at 15:22
  • 2
    setTimeout is async; while is not. It will cycle a million times through the loop before the first setTimeout concludes. The correct way to use this is with promises. Commented May 25, 2016 at 15:22
  • You should read developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop, especially the part about run-to-completion. Commented May 25, 2016 at 15:22

2 Answers 2

2

setTimeout is not the same as sleep. It's a way to set a callback to happen in x milliseconds. You're passing null as the callback, and infinitely looping in the while loop, never relinquishing the thread to the http calls.

Edit: I would recommend looking into the async library for doing things like "wait for these three callbacks to finish".

Sign up to request clarification or add additional context in comments.

6 Comments

This is also called "run to completion".
…and even if it was sleep, it would still be blocking and never allow the async callbacks to increase the count.
I removed setTimeout() line from my code because it's not relevant here (but I'm thankful to all of you who pointed that out). The while loop can be empty and it still will never detect count reaching 3.
Think of it like a microphone. Your code is a DJ holding the mic and tells three people to go look at a web page and then announce on the mic when they're done doing so. However, the DJ never hands the mic to the three people, so they can never announce that they're done.
mdickin, thanks for explaining it in layman's words. I'm truly impressed by how my question was answered so quickly.
|
0

You can fix this by using recursive function that call itself using setTimeout:

(function loop() {
   if (count < 3) {
       setTimeout(loop, 1000);
       console.log('waiting..');
   } else {
       printAll();
   }
})();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.