jack_was_taken
jack_was_taken

Reputation: 959

Async function not working

I'm using redis using node (node_redis module) and am trying to wrap my retrieval code for debugging and DRY, and having trouble understanding why the following function isnt' working.

I am a bit new to more than basic async with javascript, so I don't think this has anything to do with anything other than bad js.

This works fine but having a wrapper is pretty pointless:

// wrapper
function asyncLoad(className, id, callback) {
  redisClient.hget(className, id, callback);
}
// execution
asyncLoad('Person',1234,function(err,res) {
  if (err) {
    console.log(err);
  } else {
    var obj = JSON.parse(res);
    console.log(obj);
  }
});

I thought it would be useful for debugging and repetition if I could do this, but I'm definitely doing something wrong...

// wrapper
function asyncLoad2(className, id, callback) {
  redisClient.hget(className, id, function(err,res,callback) {
    console.log(callback);
    if (err) { 
      console.log(err);
    } else {
      var obj = JSON.parse(res);
      callback(obj);
    }
  });
}
// execution
asyncLoad2('Person',1234,function(obj) {
  //simpler way to get back a parsed object with error handling already done
}

Thanks in advance! PS - I'm aware that this is really lame error handling; I'm not expecting to use it all the time, just for select things and especially during debugging.

Upvotes: 0

Views: 86

Answers (2)

jack_was_taken
jack_was_taken

Reputation: 959

For reference, here's the final function; error logging is automatic and you can do something else with the errors if you want, and you always get back a parsed hash, which is nice DRY:

// wrapper
function asyncLoad(className, id, callback) {
  redisClient.hget(className, id, function(e,r) {
    if (e || !r) { 
      console.log('Error retrieving from database: ');
      console.log(e);
      callback(e,r);
    } else {
      var parsed = JSON.parse(r);
      callback(e,parsed);
    }
  });
}
// use
asyncLoad('Person',1234, function(e,r) {
  if (e) {
    // do something besides just log
  } else {
    // the rest of your stuff here
  }
});

And I even figured I could metaprogram reconstruction of the full object (since jsonified strings lack prototypes or functions), although this technique relies on the way I've written (and thoroughly tested!) my constructors and should be used extremely carefully:

...
var parsed = JSON.parse(r);
var obj = reconstructObj(className, parsed);
callback(e,obj);
...

function reconstructObj(className,hash) {
  //instantiate a new object of the correct class
  var obj = eval('new ' + className + '()');
  //overwrite the properties from the hash values
  for (prop in hash) {
    obj[prop] = hash[prop];
  }
  return obj;
}

Upvotes: 0

Bergi
Bergi

Reputation: 664207

function asyncLoad2(className, id, callback) {
  redisClient.hget(className, id, function(err,res,callback) {

Here you expect the redisClient to pass you the callback - but it doesn't, it just will pass the two err and res arguments. The callback parameter shadows the callback variable from the asyncLoad2 function, you will not be able to access it. Remove the parameter:

function asyncLoad2(className, id, callback) {
  redisClient.hget(className, id, function(err,res) {
     // now refer to the actual `callback` that was passed into `asyncLoad2`

Upvotes: 2

Related Questions