Sait
Sait

Reputation: 19855

Accessing global variable javascript

I am trying to download a web-page using nodejs, javascript. However it seems to have a inifinite loop. Why?

var downloadFinished = false;

var downloadPage = function(url,file) {
  rest.get(url).on('complete', function(result) {
  if (result instanceof Error) {
    console.log('Error:', result.message);
  } else {
    fs.writeFileSync(file, result, 'utf8');
    downloadFinished = true;
   }   
  }); 
};

if(require.main == module) {
    downloadPage('http://google.com', 'new.html');
    while(!downloadFinished) {
       // wait till download finished.
    } 
    // do other stuff make sure download is finished to 'new.html'
}

Upvotes: 0

Views: 49

Answers (2)

Kyle Needham
Kyle Needham

Reputation: 3389

When you call that while(!downloadFinished) it is set to false so you are basically doing while(true).

Option 1

You can use a callback instead of a while loop.

var successCallback = function() {
 //do stuff here.
};

var downloadPage = function(url, file, callback) {
  rest.get(url).on('complete', function(result) {
  if (result instanceof Error) {
    console.log('Error:', result.message);
  } else {
    fs.writeFile(file, result, 'utf8', callback);
   }   
  }); 
};

if(require.main == module) {
    downloadPage('http://google.com', 'new.html', successCallback);
}

Option 2

Check out Promises they will really help you here. You could use Bluebird a nice Promise library you can just add to your package dependencies.

Upvotes: 1

Paul
Paul

Reputation: 141927

Javascript is single-threaded, if you have a loop like:

while(!downloadFinished) {

}

that loop will keep running forever and no other function will run (your .on('complete' callback can't execute until the while loop finishes, because of the single-threaded nature of Javascript, so it won't ever finish since you don't set downloadFinished = true inside that loop or use a break statement).

To work around this, you can do all your other stuff in a callback which you don't call until the download completed:

var downloadPage = function(url, file, callback) {
  rest.get(url).on('complete', function(result) {
    if (result instanceof Error) {
      console.log('Error:', result.message);
    } else {

      /* Don't use writeFileSync, unless you want to block your server,
        from handling any requests at all until the disk IO completes

        fs.writeFileSync(file, result, 'utf8');
        callback();
      */
      fs.writeFile(file, result, 'utf8', callback);
    }   
  }); 
};

if(require.main == module) {
    downloadPage('http://google.com', 'new.html', function after_download(){
        // do other stuff make sure download is finished to 'new.html'
    });
}

Upvotes: 4

Related Questions