Reputation: 351
I have been reading about promises, wait/async and fibers for the last couple of days but I still can't wrap my head around it yet. I am having a hard time to find a simple example that shows how I can make something like this:
Meteor.methods({
theMethod: function(){
var numberOne = 4;
var numberTwo = 5;
var result = calculateNumber(numberOne, numberTwo);
console.log('This is the result: ', result);
}
});
calculateNumber = function(numberOne, numberTwo){
var result = numberOne + number Two
//but lets assume an ultra complex calculation that takes a while
return result;
}
How can I make the console.log wait for the result to come back without a callback but the await/wrapAsync syntax?
Thanks in advance! :)
EDIT:
Here is the code that I tried:
Meteor.methods({
theMethod: async function(){
const no1 = 4, no2 = 5;
//calculateNumber should return a promise, if it doesnt, Promise.resolve makes the returned value a promise
const calculateNumberPromise = Promise.resolve(calculateNumber(no1, no2));
const res = await calculateNumberPromise;
console.log('Number calculated', res);
//the number can be returned directly to the client:
return res
}
});
calculateNumber = function(no1, no2){
function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
sleep(5000).then(() => {
return no1 + no2;
});
}
Is there a way to just make everything wait that comes after the calculateNumber? If that is not possible, where/how do I have to nest the console.log to make it wait?
Upvotes: 1
Views: 260
Reputation: 390
With exclusively Promise
(ie no async
/await
), you can do something like:
Meteor.methods({
theMethod: () => {
const no1 = 4, no2 = 5;
//calculateNumber should return a promise, if it doesnt, Promise.resolve makes the returned value a promise (unless calculateNumber is a sync function ie takes a callback)
const calculateNumberPromise = Promise.resolve(calculateNumber(no1, no2));
//If you want to log the output regardless:
calculateNumberPromise
.then(res => console.log('Number calculated', res))
.catch(err => console.log('Error calcualting number', err))
//The promise is resolved before the data is sent over the wire.
return calculateNumberPromise;
}
});
On the client this method can then be called and the promise be used. Ideally you should use validated methods now. In conjunction with validated methods, you can use the callPromise mixin. Examples linked. More validated method examples can be found in the meteor guide.
Adapting the previous snippet to use async
is simple:
Meteor.methods({
theMethod: async function() {
const no1 = 4, no2 = 5;
//calculateNumber should return a promise, if it doesnt, Promise.resolve makes the returned value a promise
const calculateNumberPromise = Promise.resolve(calculateNumber(no1, no2));
const res = await calculateNumberPromise;
console.log('Number calculated', res);
//the number can be returned directly to the client:
return res;
}
});
Notice the addition of async
in the function definition. An excellent writeup can also be found here - check out Rob Fallows other articles.
wrapAsync
is simple enough, but i would suggest sticking to Promise
and async
/await
. If you really want to use it, some old (but good) examples can be found on the Meteor chef's site.
If any of that was unclear, please ask for clarification.
Upvotes: 3
Reputation: 20227
The simplest way to make an async function synchronous in Meteor is to wrap it with Meteor.wrapAsync
For your example:
Meteor.methods({
theMethod() {
const numberOne = 4;
const numberTwo = 5;
const result = Meteor.wrapAsync(asyncFun(numberOne, numberTwo));
console.log('This is the result: ', result);
}
});
Your calculateNumber
function is synchronous the way you've listed it in your question, wrapAsync
is designed to wrap a truly async function. Note that long running !== asynchronous. Note also that the async function you're wrapping must return an error and a result, not just a result. Of course when you use wrapAsync
only the result will be returned to the calling code so you'll need to use a try/catch
block to catch any errors.
Upvotes: 1