For loop get items from redis delay

I'm using Node.js w/ node_redis and am looping through an object and looking up data in Redis, then returning results.

I have it setup like this:

        for (var key in items) {
            if (items.hasOwnProperty(key)) {

                    app.client.llen(items[key].id+'_click', function(err, total) {
                        items[key].total = total;

                    });
            }
        }

       callback(items);

The problem is that it loops through, before completing the call to redis. So the callback is called, before it's actually updated the total value. It also seems to skip some items due to the delay.

Is there a better way to handle this?

Thank you!

EDIT:

Ok, so I've updated it like this:

   getTotal(function () {
       callback(items);
   });

   getTotal = function (callback) {

       var count = 1;

       for (var key in items) {
           if (items.hasOwnProperty(key)) {
               app.client.llen(items[key].id + '_click', function (err, total) {
                   items[key].total = total;

                   if (items.length == count) {
                       callback();
                   }

                   count++;
               });
           };
       }

This seems like it would work, it triggers the callback at the appropriate time, however it seems only the last key is getting total updated.

Your first example cannot work because a loop is synchronous while the Redis client calls are asynchronous. Your second example does not work much better because of Javascript closure management. You need a proper scope in the loop itself so the closure is handled correctly, and all the total fields updated accordingly.

Using forEach seems to be easier here:

getTotal = function (callback) {
  var count = 0;
  Object.keys( items ).forEach( function(key) {
    ++count;
    app.client.llen(items[key].id + '_click', function (err, total) {
      items[key].total = total;
      if ( --count == 0 ) {
        callback( items );
      }
    })
  })
}

getTotal( function(items) {
  console.log( items );
})