简体   繁体   中英

cannot catch Meteor.Error in client when error in server inside Meteor.bindEnvironment

I am not able to get the error in client's Meteor.call error callback when in the server code, an error occurs inside Meteor.bindEnvironment . Below is example code to replicate

In the server

Meteor.methods({
  customMethod: function(arg1, arg2){
      Stripe.customers.create({
        email: "email@here.com,
        description: "blah blah",
        source: token,
        metadata: {
          planId: planId,
          quantity: n
        },
        plan: planId,
        quantity: n
      }, Meteor.bindEnvironment(function (err, customer) {
        if(err){
          console.log("error", err);
          // TODO cannot catch this error on the client
          throw new Meteor.Error(err.rawType, err.message)
        }
      }))
    }
})

In the client inside a Meteor event,

Meteor.call('customMethod', arg1, arg2, function (err, resp) {
 if(err){
   Session.set('some-error', err)
 }
 if(resp){
   // TODO cannot catch errors throwing from the server
   // when inside Meteor.bindEnvironment 
   Session.set('some-success', true)
 }
});

The session variables are never set. Any help would be great. Thanks!

The second argument to Meteor.bindEnvironment is an error-handler that gets called whenever an exception is thrown within the callback you supplied as the first argument. So you can do something like this to get the error passed back to the client:

Meteor.bindEnvironment(function (err, customer) {
  if (err) throw err
  ...
}, function (err) {
  if (err) throw new Meteor.Error(err.message)
})

UPDATE

Apologies, that was a bit hasty. The problem is the fact that your error (and potentially results) are coming from an asynchronous callback, so your method function will have finished executing, and implicitly returned undefined (which gets passed to the client as null ) by the time the callback does anything.

Historically, you'd resolve this with a future , but now we have promises, which are better:

Meteor.methods({
  customMethod (arg1, arg2) {
    return new Promise((resolve, reject) => {
      Stripe.customers.create({
        email: "email@here.com,
        ...
      }, Meteor.bindEnvironment(function (err, customer) {
        if(err){
          reject(err)
        }
        resolve(customer)
      })).catch(e => { throw new Meteor.Error(e) })
  }
})

Meteor methods are clever enough to wait for promises to resolve or reject and return the result (or error) via DDP. You still need to catch the error and formally throw it, but your method call will wait for you to do so.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM