I just realized something fundamentally wrong in this approach and that nested callbacks can't return something to its parent callback. I came in late in the JS world and come from the Promises
era and didn't know this is the problem with callbacks. But I didn't see enough examples for Meteor using promises so I used callbacks instead. However, if this code can be improved I'd appreciate it greatly.
So I'm calling a method from the client using:
Meteor.call('cart.useProfileAddress', {}, (error, address) => {
console.info('Address', address) // this returns undefined on client
})
This is the method in my api/carts/cartsMethod.js
export const useProfileAddress = new ValidatedMethod({
name: 'cart.useProfileAddress',
validate(args) {
//
},
run(args) {
const person = Persons.findOne({'userId': Meteor.userId()});
// If I do the return here I get the address in the browser as defined.
// return person.address
// I'm calling another method under here:
getClosestStore.call({address: person.address}, (error, result) => {
// And another one method call here:
updateCartAddress.call({address: person.address}, (error, result) => {
// So once all the callbacks are done return the address here.
// However the problem is I get `undefined` on the client.
if (!error) {
// console displays something on the Server but is `undefined` on the Client
console.info('Returning Address', person.address)
return person.address
}
})
})
}
})
What could be the problem on the code above? Could it be because I'm trying to get the value from a nested callback?
Also does anyone know how to avoid these nested callbacks? I know how to do it on Node
using promises but in Meteor (I'm using 1.4
) I'm still clueless.
This is how I solved my problem using Promise and the new async/await
feature of Meteor 1.3+
export const useProfileAddress = new ValidatedMethod({
name: 'cart.useProfileAddress',
validate(args) {
//
},
run(args) {
return ((async () => {
const person = Persons.findOne({'userId': Meteor.userId()});
const storeId = await getClosestStore.callPromise({address: person.address})
const newAddress = await updateCartAddress.callPromise({address: person.address})
return newAddress
})())
}
})
Inside each method I used the didericis:callpromise-mixin so that it will return a promise.