codeyashu codeyashu - 1 month ago 20
Javascript Question

implementing javascript callback with loop

I am new to asynchronous programming and cant seem to solve this problem.
I am building this node.js app to serve stock quotes and basically what i need to do is query a database to get details of various companies. I need to send a request to api with company details as parameters which gives me the quote and then I need to update the database with new quote. So basically i need to do this for each company in the database. (I am using rethinkdb as my database)

This is my code



query.companyList(function(err, data){
if(err) {
console.log(err);
}
else {

for(var i = 0;i < 6;i++){
var comp = data.clist[i].exchange+ ':' +data.clist[i].ticker;
console.log(comp);
var cid = data.clist[i].id;
console.log(cid);

googleStocks([comp])
.then(function(data){
console.log((data[0].lt));
r.table('company').get(parseInt(cid)).update({quote:{lastTradeTime:data[0].lt, lastTradePrice:data[0].l_cur, change:data[0].c, changePercent:data[0].cp}}).run()
.then(function(results){
console.log(results);
})
.catch(function(err){
console.log(err);
});
})
.catch(function(error){
console.log(error);
});
}
}
});





I know this is not an asynchronous code as the output of console.logs is pretty random.

So in short I need to send and API request and update the quotes for each company in my database.

My output:

Server started!

NASDAQ:MSFT

358464

NYSE:F

13606

NSE:TATAMOTORS

9708440

NASDAQ:FB

296878244325128

undefined:undefined

b90630ec-0a95-4373-93f8-2c36a336335d

NASDAQ:AAPL

22144

Webservice returned 400

Nov 8, 11:35AM EST

Nov 8, 3:50PM GMT+5:30

Nov 8, 11:35AM EST

Nov 8, 11:35AM EST

Nov 8, 11:35AM EST

{ deleted: 0,

errors: 0,

inserted: 0,

replaced: 1,

skipped: 0,

unchanged: 0 }

{ deleted: 0,

errors: 0,

inserted: 0,

replaced: 1,

skipped: 0,

unchanged: 0 }

{ deleted: 0,

errors: 0,

inserted: 0,

replaced: 1,

skipped: 0,

unchanged: 0 }

{ deleted: 0,

errors: 0,

inserted: 0,

replaced: 1,

skipped: 0,

unchanged: 0 }
{ deleted: 0,

errors: 0,

inserted: 0,

replaced: 1,

skipped: 0,

unchanged: 0 }

Ignore "undefined:undefined" and "Webservice returned 400".

So what i would like to get for each company the status of update command

NASDAQ:MSFT

358464
{ deleted: 0,

errors: 0,

inserted: 0,

replaced: 1,

skipped: 0,

unchanged: 0 }

I am sorry if I am not clear enough.

Answer

Try something like this:

query.companyList(function(err, data){
      if(err) {
         console.log(err);
      } 
      else {

        for(var i = 0;i < 6;i++){
           var comp = data.clist[i].exchange+ ':' +data.clist[i].ticker;
           console.log(comp);
           var cid = data.clist[i].id;
           console.log(cid);
           (function(_id) {
               googleStocks([comp])
               .then(function(data){
                 console.log((data[0].lt));
                 r.table('company').get(parseInt(_id)).
                     update({quote:{lastTradeTime:data[0].lt,
                         lastTradePrice:data[0].l_cur, change:data[0].c, 
                             changePercent:data[0].cp}}).run()
                 .then(function(results){
                   console.log(results);
                 })
                 .catch(function(err){
                   console.log(err);
                 });
               })
               .catch(function(error){
                 console.log(error);
               });
            })(cid);
        }
      }
});

I did not run the code because I don't have the environment to. But it should point you in the right direction.

Yes, what happens is the for loop will run six times and each time the async call is made. By the time the result came back, the cid variable contains the last id and only the last id gets updated six times.

You enclosing the code block into an anonymous function and pass it cid, we ensure that the real id is used each time.