-2

I'm trying to get some information from a web page using request to get the page and then cheerio to traverse the DOM to the specific part I need I'm repeating this process for multiple elements in an array using array.forEach using this code:

const cheerio = require('cheerio');
const request = require('request');
var i = 0;
var rates = [];
['AUD', 'CAD'].forEach(function(currancy){
  var url = "https://www.google.com/finance/converter?a=1&from=USD&to=" + currancy
  request(url , function(error, res , body){
    const $ = cheerio.load(body);
    var temp = $('.bld');
    var rate = temp.text();
    console.log(rate);
    rates[i]= rate;
    i++;
  })
});
console.log('done');

the result I'm expecting is something like this:

1.31 AUD
1.28 CAD
done

but I'm getting this insted:

done
1.31 AUD
1.28 CAD

can you tell me why is array.forEach not blocking my code?

  • 2
    It *is* blocking the code, but an async request *is non-blocking*... it `forEach`s over the array and for every element, sends a request which is async. The last log is executed before the requests finish. – Andrew Li Jul 09 '17 at 22:56
  • @AndrewLi make it an answer for future reference – taha Jul 09 '17 at 23:03
  • 3
    This general type of question (a misunderstanding of how asynchronous calls work in nodejs) is asked multiple times per day here. There are hundreds of related questions/answers here. – jfriend00 Jul 09 '17 at 23:04
  • contemplating https://stackoverflow.com/q/5050265/497418 and https://stackoverflow.com/q/14220321/497418 as dupes. neither quite fit – zzzzBov Jul 09 '17 at 23:06
  • 1
    This one shows how you tell when multiple asynchronous calls are done (which is what is really going on here): [Tracking when multiple async calls are done](https://stackoverflow.com/questions/44992100/why-am-i-not-able-to-access-the-scope-of-this/44993439#44993439) – jfriend00 Jul 09 '17 at 23:10

1 Answers1

2

You are printing 'done' before any of your http requests to google return.

You loop though the currencies, making a call to google for each one, and print 'done'. Then the calls start to return (in random order, btw) and you print the results.

So, the forEach isn't asynchronous, but the http requests are.

Software Engineer
  • 15,457
  • 7
  • 74
  • 102