user3284007
user3284007

Reputation: 1717

Waiting for operation to finish in node.js

I'm new to Node.js. I'm trying to use the Node Redis plugin. What I'm trying to do is get the list of key/value pairs from a REDIS database. The asynchronous nature of Node is creating a challenge for me. When I try to print the key/value pairs, my array is empty. I think its because my query to the database hasn't completed yet.

The reason I'm creating an array first instead of just printing out the key/value pairs, is because I want to sort the results alphabetically by either key or value. Currently, I"m trying the following:

redisClient.on('connect', function() {
  var pairs = [];
  redisClient.keys('*', function (err, keys) {
    if (err) { return console.log(err); }
    for(var i = 0, len = keys.length; i < len; i++) {
      (function(key) {
        redisClient.get(key, function(err, v) {
          pairs.push({ key: key, value: v });
        });
      })(keys[i]);
    }
  });

  // List of key/value pairs ordered alphabetically
  console.log(pairs);
});

Can someone tell me how to get beyond this issue? Thank you

Upvotes: 0

Views: 676

Answers (2)

Alex Turpin
Alex Turpin

Reputation: 47776

You are right in your assertion that when console.log is executed, nothing has happened yet. To deal with this kind of problem in Node.js, some people like to use modules like async and others prefer to use promises (a popular library for promises is Q).

Here is a solution using async.

var async = require('async');

redisClient.on('connect', function() {
  redisClient.keys('*', function (err, keys) {
    if (err) { return console.log(err); }

    async.map(keys, function(key, callback) {
      redisClient.get(key, function(err, value) {
        callback(null, {key: key, value: value});
      });
    }, function(err, pairs) {
      console.log(pairs);
    });
  });
});

async just happens to have a map function that takes an array, applies a function asynchronously to each elements and creates an array with the results.

Upvotes: 2

Vinz243
Vinz243

Reputation: 9958

You need to use recursion:

do = function(i, data, callback){
    // if the end is reached, call the callback
    if(data.length === i+1)
       return callback()
    obj = data[i]
    redisClient.get(key, function(err, v) {
      pairs.push({ key: key, value: v });
      i++;
      // call do with the next object
      do(i, data, callback)
    });

}
// Redis...
do(0, keys, function(){
    // List of key/value pairs ordered alphabetically
    console.log(pairs);
});

Upvotes: 0

Related Questions