It’s a bit different to that SO answer since you’re using an async method
The problem is that the method has returned before your callback runs and so the error doesn’t get thrown in the context of a method and doesn’t get sent to the client.
The general flow of your function currently is:
** Method comes in
>> Send aync function request to send sms
** return empty response to client -> client sees no error
<< async function finishes and runs callback, here error is set, so you try to send to client by throwing, but empty response already sent to client.
What you want to do is wait for the callback to finish first.
There’s three ways you can do this with Meteor
1. Use Meteor.wrapAsync
// Wrap the function you want to call
// The second parameter sets `this` in the wrapped function.
// I have no idea if the GoogleApi module you're using needs this, but I'm including it just in case
const wrappedApi = Meteor.wrapAsync(api.VerifyLookup, api);
// (...)
'sendSMS'() {
api.VerifyLookup(, function(response, status) {
});
try {
const status = wrappedApi({
receptor: ToRegister.phone_number,
token: auth_code,
template: "register"
});
if ( status !== 200) {
throw new Meteor.Error(400,'somthing ','somthing');
}
} catch (error) {
throw new Meteor.Error(400,'somthing ', error);
}
}
Here’s the docs on Meteor.wrapAsync
:
Long before Promises and async functions, Meteor provided sync style async calls on the server using Fibers
. If you’re curious, you can get a rundown here: https://benjamn.github.io/goto2015-talk/#/
2. Return a Promise:
'fetchMessages'() {
// Return the promise, that will *eventually* resolve with the value you want to send
return new Promise(function (resolve, reject) {
api.VerifyLookup({
receptor: ToRegister.phone_number,
token: auth_code,
template: "register"
}, function(response, status) {
if ( status !== 200) {
reject(new Meteor.Error(400,'somthing ','somthing'));
}
resolve(status);
});
});
}
This works because Meteor checks if you’re returning a promise from a method and will automatically await the result before sending it to the client
3. Use Async/Await
async functions
and async/await
work best in when the library you’re using already returns promises or if you can promisify the function in question.
I’ll use the pify
module to promisify the function in the example
import pify from 'pify'
// promisify the function you want to call
const wrappedApi = pify(api.VerifyLookup);
(...)
// Change the function declaration to an async function
'sendSMS': async function() {
// Now when we run the promisified function it returns a promise that we
// can wait for the value of with `await`
try {
const status = await wrappedApi({
receptor: ToRegister.phone_number,
token: auth_code,
template: "register"
});
if ( status !== 200) {
throw new Meteor.Error(400,'somthing ','somthing');
}
return status;
} catch (error) {
throw new Meteor.Error(400,'somthing ', error);
}
}
Note that await
is only available inside an async function
. async
functions always return a promise.
This one is most similar to the Meteor example, except that it uses pure javascript.
One notable difference is that when Meteor sees an async function it acts as though you ran this.unblock()
inside the function, and so the order in which methods are called is not guaranteed (unlike with wrapAsync
).