Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
723 views
in Technique[技术] by (71.8m points)

javascript - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 );
})

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...