MisutoWolf
MisutoWolf

Reputation: 1233

Problems with my async wrapping Meteor package

I'm trying to author my first Meteor smart package at the current time, and have hit a problem.

I'm trying to write a package that wraps the following node.js module: https://github.com/dmcquay/node-apac

I was advised that in doing so, I should wrap the OperationHelper.execute() method using Meteor._wrapAsync to avoid callback hell when using it in future projects.

I have the following code currently in my package:

apac = Npm.require("apac");
OperationHelper = apac.OperationHelper;
 
function makeSyncMethod(method){
    var wrapped=Meteor._wrapAsync(method);
    var syncMethod=function(){
        return wrapped.apply(this,arguments);
    };
    return syncMethod;
}

OperationHelper.prototype.executeSync = makeSyncMethod(OperationHelper.prototype.execute);

It seems to be extending the prototype the way it's supposed to (I think), but when I go to call it using the following code (I just created a barebones Meteor project, added my package, and that's all):

// Test of APAC stuff, maybe.

Meteor.startup(function() {

    opHelper = new OperationHelper({
        awsId: "<key>",
        awsSecret: "<key>",
        assocId: "<id>"
    });

    var test = opHelper.executeSync('ItemLookup', {
        SearchIndex: 'Books',
        ResponseGroup: 'Small,Images',
        IdType: 'ISBN',
        ItemId: '9780078025600'
    });
 
    console.log(JSON.sringify(test));

});

I get the following output (best I could do was a screenshot from the VM the code is being executed in: error screenshot

I have no idea what is going on. I'm new to Meteor, and was just using this apac stuff via meteor-npm before, but I was told writing a smart package wrapper with async would be far better than what I was previously doing.

Any help would be greatly appreciated.

Upvotes: 1

Views: 197

Answers (1)

user3374348
user3374348

Reputation: 4101

Meteor._wrapAsync expects the function it's wrapping to use the standard node.js function (err, result) error reporting convention:

doSomethingAsync(arg1, arg2, function (err, result) {
  if (err) {
    // error occurred
  } else {
    // all is well
  }
});

But apac uses a different error reporting convention:

opHelper.execute("...", {
  //...
}, function (result) {
  // all is well
}, function (err) {
  // error occurred
});

(The version of apac in the GitHub repository uses the standard convention, but it hasn't been pushed to npm since it's a breaking change.)

I guess when apac delivers the result as the first argument to the callback, _wrapAsync mistakes it for an error, and throws an exception.

You'll have to convert to the node.js convention before passing into _wrapAsync. Try this:

OperationHelper.prototype.executeSync = Meteor._wrapAsync(function (name, args, callback) {
  callback = _.once(callback); // work around apac bug
  this.execute(name, args, function (result) {
    callback(null, result);
  }, function (err) {
    callback(err);
  });
});

Upvotes: 2

Related Questions