Reputation: 1430
I have a Meteor method that tries to manipulate the database, and if successful, calls an async method. I would like to be able to call this method and return the result of the async call or the error from the database manipulation.
This is (roughly) my code on the server:
Meteor.methods({
'data.update'(id, data) {
Collection.update({id_: id}, {$set: {data: data}}, error => {
if (error) {
// Have method return Meteor error for DB-failure
} else {
callAsync(id, (error, res) => {
if (error) {
// Have method return Meteor error for async call failure
} else {
// Have method return success(res)
}
})
}
})
}
});
I have read about Futures and Promises, but I'm new to the concepts and I'm not sure when to use what. Preferably I'm looking for a solution that does not rely on any third party libraries outside of Meteor/ES6. Bonus (related) question: what is normally returned after a database manipulation that let's me attach a callback to a method?
Upvotes: 1
Views: 348
Reputation: 1128
According to docs
On the server, if you don’t provide a callback, then update blocks until the database acknowledges the write, or throws an exception if something went wrong. If you do provide a callback, update returns immediately. Once the update completes, the callback is called with a single error argument in the case of failure, or a second argument indicating the number of affected documents if the update was successful.
So, if the update
is successful, the number of documents affected is returned. In case of insert
, the _id
of the inserted document is returned.
You can simply pass a third argument to the update function as mentioned.
For promise implementation, you can use Meteor.wrapAsync
method. You may also want to look at Meteor.bindEnvironment
to achieve that, if you need to pass the state of instance variables too.
Upvotes: 3
Reputation: 1399
You can look into using Promises, but there is another fairly standard way of handling something like this within the Meteor ecosystem. You can use Meteor.wrapAsync
to convert your asynchronous callback based function into a Fibers based version. This will then let you leverage return values and exceptions. Here's a quick example:
1) Let's say we have an internal function somewhere called increaseLifetimeWidgetCount
that increases our lifetime widget count in the database somewhere, then calls a callback with either an error or the newly updated lifetime count:
function increaseLifetimeWidgetCount(callback) {
// ...
// increase the lifetime widget count in the DB somewhere, and
// get back the updated widget count, or an error.
// ...
const fakeError = null;
const fakeLifetimeWidgetCount = 1000;
return callback(fakeError, fakeLifetimeWidgetCount);
}
2) Let's say we then have a simple Method defined that will create a new Widget in our database, call our internal increaseLifetimeWidgetCount
function, then return the newly updated lifetime widget count. Since we want to return the updated lifetime widget count, we'll wrap our callback based increaseLifetimeWidgetCount
function in a Meteor.wrapAsync
call, and return the result:
Meteor.methods({
newWidget(data) {
check(data, Object);
Widgets.insert(data);
const increaseLifetimeWidgetCountFiber =
Meteor.wrapAsync(increaseLifetimeWidgetCount);
const lifetimeWidgetCount = increaseLifetimeWidgetCountFiber();
return lifetimeWidgetCount;
}
});
3) We can then call the newWidget
Method from our client, with an asynchronous callback, and handle either the returned error or returned lifetime widget count:
Meteor.call('newWidget', {
name: 'Test Widget 1'
}, (error, result) => {
// Do something with the error or lifetime widget count result ...
console.log(error, result);
});
Upvotes: 1