Just getting started with Bluebird and trying to figure out the best way to promisify use of the sendTemplate call on the mandrill-api. It's not a standard node.js callback design in that it takes 2 callback as the last parameters (first as a success callback and the second being a failure callback). For example (taken from the mandril docs)
mandrill_client.messages.sendTemplate({"template_name": template_name, "template_content": template_content, "message": message, "async": async, "ip_pool": ip_pool, "send_at": send_at}, function(result) {
// SUCCESS
console.log(result);
/*
[{
"email": "[email protected]",
"status": "sent",
"reject_reason": "hard-bounce",
"_id": "abc123abc123abc123abc123abc123"
}]
*/
}, function(e) {
// FAILURE
// Mandrill returns the error as an object with name and message keys
console.log('A mandrill error occurred: ' + e.name + ' - ' + e.message);
// A mandrill error occurred: Unknown_Subaccount - No subaccount exists with the id 'customer-123'
});
Any help/suggestions would be great. At a minimum we'd like to call this from inside a method wrapped in a Promise.method
@pazrul to follow
The promise constructor works pretty well with dual callback apis.
// impl
function sendTemplate(opts) {
return new Promise(function (resolve, reject) {
mandrill_client.messages.sendTemplate(opts, resolve, reject)
})
}
// usage
sendTemplate({
"template_name": template_name,
"template_content": template_content,
"message": message,
"async": async,
"ip_pool": ip_pool,
"send_at": send_at
})
.then(handleSuccess)
.catch(handleError)
If it's just one method then you can do what @wavded said.
If you want to promisify whole module that has this convention, then use a custom promisifier using the promisifier option:
Promise.promisifyAll(..., {
promisifier: function(cbApi) {
return function() {
var args = [].slice.call(arguments);
var self = this;
return new Promise(function(resolve, reject) {
args.push(resolve, reject);
cbApi.apply(self, args);
});
};
}
});
@wavded Just wanted to say that your solution is awesome and saved me a lot of headaches.
Using npm Q:
return Q.Promise(function (resolve, reject, notify) {
mandrill_client.messages.sendTemplate(opts, resolve, reject);
});
Thanks @wavded
This was really helpful @wavded. Shouldn't the sendTemplate function return the promise though instead of just create it? Thanks!
More generically:
Object.keys(mandrill_client.messages).forEach(function (key) {
mandrill_client.messages[key + 'Async'] = function (opts) {
return new Promise(function (resolve, reject) {
mandrill_client.messages[key](opts, resolve, reject);
});
};
});
Most helpful comment
The promise constructor works pretty well with dual callback apis.