adrianmcli
adrianmcli

Reputation: 1996

Calling a Meteor Method inside a Promise Callback [Halting w/o Error]

I'm trying to use this NPM package: Gumroad-API inside my Meteor app. I'm encountering issues on the server side when I try to do a Meteor method call (or a collection insert) inside of the Promise callback.

The following is the code for my two Meteor methods:

Meteor.methods({

  testMethod: () => {
    console.log('TEST METHOD RUN');
  },

  fetchGumroadData: () => {
    const Gumroad = Meteor.npmRequire('gumroad-api');
    let gumroad = new Gumroad({ token: Meteor.settings.gumroadAccessKey });

    Meteor.call('testMethod');        // runs fine

    gumroad.listSales('2014-12-04', '2099-12-04', 1).then((result) => {
      console.log('1');               // runs fine
      Meteor.call('testMethod');      // execution halts here w/o error msg
      console.log('2');               // this never runs
    });
  },
});

The code inside the .then() callback always halts (without error msgs) whenever I try to do a Meteor.call() inside of it.

I get the same behaviour when I replace the Meteor.call() with a Collection.insert() such as: Sales.insert({text:'test'});.

Upvotes: 2

Views: 430

Answers (3)

Steve Ross
Steve Ross

Reputation: 1218

Old question but, the reason this fails is because the Meteor environment is not available in your callback.

caveat this is untested code

Meteor.methods({

  testMethod: () => {
    console.log('TEST METHOD RUN');
  },

  fetchGumroadData: () => {
    const Gumroad = Meteor.npmRequire('gumroad-api');
    let gumroad = new Gumroad({ token: Meteor.settings.gumroadAccessKey });

    Meteor.call('testMethod');        // runs fine

    gumroad.listSales('2014-12-04', '2099-12-04', 1)
      .then(Meteor.bindEnvironment((result) => {
        console.log('1');               // runs fine
        Meteor.call('testMethod');      // execution halts here w/o error msg
        console.log('2');               // this never runs
      }));
    },
});

Tutorials on bindEnvironment and wrapAsync can be found here: https://www.eventedmind.com/items/meteor-what-is-meteor-bindenvironment

Upvotes: 2

adrianmcli
adrianmcli

Reputation: 1996

I ended up ditching the NPM package and writing my own API call. I could never figure out how to make my call inside the .then(). Here's the code:

fetchGumroadData: () => {
  let options = {
    data: {
      access_token: Meteor.settings.gumroadAccessKey,
      before: '2099-12-04',
      after: '2014-12-04',
      page: 1,
    }
  };
  HTTP.call('GET', 'https://api.gumroad.com/v2/sales', options, (err,res) => {
    if (err) {  // API call failed
      console.log(err);
      throw err;
    } else {    // API call successful
      Meteor.call('testMethod');
    }
  });
}

Upvotes: 0

bluebird
bluebird

Reputation: 640

I don't use promises much, so I don't know why you are seeing that error. When using external APIs like that i typically use wrapAsync so I can write my code in a synchronous fashion but still achieve the same results.

In your case that would look something like this:

Meteor.methods({

  testMethod: () => {
    console.log('TEST METHOD RUN');
  },

  fetchGumroadData: () => {
    const Gumroad = Meteor.npmRequire('gumroad-api');
    let gumroad = new Gumroad({ token: Meteor.settings.gumroadAccessKey });

    Meteor.call('testMethod');        // runs fine

    let wrappedListSales = Meteor.wrapAsync(gumroad.listSales, gumroad);

    let result = wrappedListSales('2014-12-04', '2099-12-04', 1);

    console.log('1');               
    Meteor.call('testMethod');      
    console.log('2');               
  },
});

The second argument to Meteor.wrapAsync is optional and may not be needed, depending on the nature of the gumroad API

Upvotes: 0

Related Questions