Hello
I am trying to insert some data in a collection after an asynchronous api call in the Accounts.onCreateUser callback (API: https://github.com/Mangopay/mangopay2-nodejs-sdk).
However I am getting the error:
throw new Error("Meteor code must always run within a Fiber. " + Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.
Here’s my first try:
Accounts.onCreateUser(function(options, user) {
mangoPayApi.Users.create({
"Email": options.email,
"FirstName": options.profile.firstName,
"LastName": options.profile.lastName,
"CountryOfResidence": "FR",
"Nationality": "FR",
"Birthday": new Date(aBirthDateTimestamp).getTime() / 1000,
"PersonType": "NATURAL",
"Tag": user._id,
}, function(mpUser) {
// User created - using callback
console.log('User created ');
console.log(mpUser);
aMPData.user = mpUser;
MPData.insert(aMPData); // Insert data into collection`
Second shot: I tried to make the api call aynchronous
let synCreateUser = Meteor.wrapAsync(mangoPayApi.Users.create, mangoPayApi.Users ); user = handleCharge.create({ "Email": post.emails[0], "FirstName": post.profile.firstName, "LastName": post.profile.lastName, "CountryOfResidence": "FR", "Nationality": "FR", "Birthday": new Date(aBirthDateTimestamp).getTime() / 1000, "PersonType": "NATURAL", "Tag": post._id, });
But now I get the following error:
Exception in queued task: TypeError: Object function (/* arguments */) {
ar self = context || this;
var newArgs = _.toArray(arguments);
var callback;
for (var i = newArgs.length - 1; i >= 0; --i) {
var arg = newArgs[i];
var type = typeof arg;
if (type !== "undefined") {
if (type === "function") {
callback = arg;
}
break;
}
}
if (! callback) {
if (Meteor.isClient) {
callback = logErr;
} else {
var fut = new Future();
callback = fut.resolver();
}
++i; // Insert the callback just after arg.
}
newArgs[i] = Meteor.bindEnvironment(callback);
var result = fn.apply(self, newArgs);
return fut ? fut.wait() : result;
} has no method 'create'
at Object.added (server/main.js:102:30)
at [object Object].observeChangesCallbacks.added (packages/minimongo/observe.js:153:1)
at self.applyChange.added (packages/minimongo/observe.js:53:1)
`
Now my question is, how can I insert the data I get from an async api call into a collection ?
UPDATE: On my second try, I made a mistake
Following @robfallows advice I tried:
try {
let mangopayuser = Meteor.wrapAsync( mangoPayApi.Users.create, mangoPayApi.Users );
be = mangopayuser({
"Email": options.email,
"FirstName": options.profile.firstName,
"LastName": options.profile.lastName,
"CountryOfResidence": "FR",
"Nationality": "FR",
"Birthday": new Date(aBirthDateTimestamp).getTime() / 1000,
"PersonType": "NATURAL",
"Tag": user._id,
});
} catch (err) {
console.log('2');
console.log(err);
console.log('3'); }
which yields the following:
[details=Console output]I20160630-20:29:12.229(2)? onCreateUser
I20160630-20:29:13.512(2)? 2
I20160630-20:29:13.517(2)? { Address:
I20160630-20:29:13.518(2)? { AddressLine1: null,
I20160630-20:29:13.518(2)? AddressLine2: null,
I20160630-20:29:13.519(2)? City: null,
I20160630-20:29:13.520(2)? Region: null,
I20160630-20:29:13.520(2)? PostalCode: null,
I20160630-20:29:13.521(2)? Country: null },
I20160630-20:29:13.521(2)? FirstName: ‘AA’,
I20160630-20:29:13.522(2)? LastName: ‘BB’,
I20160630-20:29:13.523(2)? Birthday: 689814000,
I20160630-20:29:13.523(2)? Nationality: ‘FR’,
I20160630-20:29:13.524(2)? CountryOfResidence: ‘FR’,
I20160630-20:29:13.525(2)? Occupation: null,
I20160630-20:29:13.525(2)? IncomeRange: null,
I20160630-20:29:13.526(2)? ProofOfIdentity: null,
I20160630-20:29:13.527(2)? ProofOfAddress: null,
I20160630-20:29:13.527(2)? PersonType: ‘NATURAL’,
I20160630-20:29:13.528(2)? Email: ‘b@b.fr’,
I20160630-20:29:13.529(2)? KYCLevel: ‘LIGHT’,
I20160630-20:29:13.529(2)? Id: ‘14407486’,
I20160630-20:29:13.530(2)? Tag: ‘S8d4zPBpYfjsxDkEH’,
I20160630-20:29:13.531(2)? CreationDate: 1467311353 }
I20160630-20:29:13.542(2)? 3[/details]
I gotta say that blew my mind. In err, there’s my api response??
UPDATE 2
Following @youngone suggestion, I managed to make it work ! Since, there are some nested callbacks here the full solution as someone may find it useful
/* Create MangoPay user */
mangoPayApi.Users.create({
"Email": options.email,
"FirstName": options.profile.firstName,
"LastName": options.profile.lastName,
"CountryOfResidence": "FR",
"Nationality": "FR",
"Birthday": new Date(aBirthDateTimestamp).getTime() / 1000,
"PersonType": "NATURAL",
"Tag": user._id,
}, Meteor.bindEnvironment( function(mpUser) {
// User created - using callback
console.log('User created ');
console.log(mpUser);
aMPData.user = mpUser;
if(mpUser)
{
mangoPayApi.Wallets.create({
"Owners": [mpUser.Id],
"Description": "User Wallet",
"Currency": "EUR"
}, Meteor.bindEnvironment( function(wallet) {
console.log('wallet created');
console.log(wallet);
aMPData.wallet = wallet;
/* MangoPay wallet created */
/* Create MangoPay CardRegistrations for user */
if(wallet)
{
mangoPayApi.CardRegistrations.create({
"UserId": wallet.Owners[0],
"Currency": "EUR",
"CardType": "CB_VISA_MASTERCARD"
}, Meteor.bindEnvironment( function(cardRegistration) {
console.log('cardRegistration');
console.log(cardRegistration);
if (cardRegistration)
{
aMPData.cardRegistration = cardRegistration;
/* Everything is OK, insert it in DB */
MPData.insert(aMPData);
}
})); // callback mangoPayApi.CardRegistration
} // end if wallet
})); // callback mangoPayApi.Wallets // Meteor.bindEnvironment callback angoPayApi.Wallets // mangoPayApi.Wallets.create
} // end if mpUser
})); // callback Users.create // Meteor.bindEnvironment callback Users.create// mangoPayApi.Users.create;
Now, how can may I catch exceptions thrown by the api call ?