Reputation: 3427
Alright, noob here. Still learning. I don't understand how I get my method to return the result of my Meteor.wrapAsync
function to the Meteor.call on the client. My console.log(companies);
in my method produces a function and not the result. What am I not understanding here?
Path: client.jsx
Meteor.call('getTop100ASX', (error, result) => {
console.log(result);
});
Path: method.js
Meteor.methods({
'getTop100ASX'() {
const aggregateFunc = db.collection('companiesASX').aggregate([{
$group: {
_id: {
location: "$google_maps.geometry_location"
},
companies: {
$addToSet: {
name: "$company_name"
}
}
}
}]).toArray((err, result) => {
return result;
});
const companies = Meteor.wrapAsync(aggregateFunc);
console.log(companies);
return companies;
},
});
Upvotes: 1
Views: 822
Reputation: 16488
wrapAsync
wraps a function that would normally take a callback and makes it possible to call that wrapped function on the server in a synchronous fashion, utilizing fibers
(i.e, takes a function + context and returns a function).
It cannot take some value and magically extract the intended result from it (i.e, in your example, the the result
from the toArray
callback).
What you gave it is not a function, but a Promise
object (that was returned from the call to toArray
).
Since it already returns a promise, you have several options:
The simpler one is to return that promise (and there is no need for the callback in toArray()
), since if a Meteor method returns a promise, the server will wait for the promise to resolve and then returns the result to the client.
Meteor.methods({
'getTop100ASX'() {
return db.collection('companiesASX').aggregate([...]).toArray();
},
});
If you need to further process companies
in the method, you could use async/await, something like:
Meteor.methods({
async 'getTop100ASX'() {
const companies = await db.collection('companiesASX').aggregate([{
$group: {
_id: {
location: "$google_maps.geometry_location"
},
companies: {
$addToSet: {
name: "$company_name"
}
}
}
}]).toArray();
let someResult = sumeFunc(companies);
return someResult;
},
});
For completeness, in order to use wrapAsync
, you should have supplied the toArray
method and the context like so:
Meteor.methods({
'getTop100ASX'() {
const cursor = db.collection('companiesASX').aggregate([{
$group: {
_id: {
location: "$google_maps.geometry_location"
},
companies: {
$addToSet: {
name: "$company_name"
}
}
}
}]);
// wrap the cursor's `toArray` method and preservs the context
const syncToArray = Meteor.wrapAsync(cursor.toArray, cursor);
// and call the wrapped function in a sync manner
const companies = syncToArray();
return companies;
},
});
Upvotes: 2