I am creating a node module and I want to be able to support both node callback and Promise APIs. The library that I hear the best things about (mainly that is it the fastest) is bluebird. So after reading some docs and looking at some other libraries that are using bluebird, I thought this would be the cleanest way to get a method to support both node callback and Promise APIs:
this.isAllowed = function(role, resource, permission, callback) {
var isAllowedAsync = bluebird.promisify(isAllowed);
return isAllowedAsync(role, resource, permission).nodeify(callback);
};
However with this code, the callback is never executed. After some more research, I tried this:
this.isAllowed = function(role, resource, permission, callback) {
return new bluebird(function (resolve, reject) {
resolve(isAllowed(role, resource, permission));
}).nodeify(callback);
};
With that code, both the node callback and Promise API works.
For reference, this is the isAllowed method:
var isAllowed = function(role, resource, permission) {
if(!lists[role] || !lists[role][resource]) {
return false;
}
return lists[role][resource].indexOf(permission) !== -1;
};
Am I doing something wrong in the first code example or is the second example the real way of getting what I am looking for?
I am creating a node module and I want to be able to support both node callback and Promise APIs. The library that I hear the best things about (mainly that is it the fastest) is bluebird. So after reading some docs and looking at some other libraries that are using bluebird, I thought this would be the cleanest way to get a method to support both node callback and Promise APIs:
this.isAllowed = function(role, resource, permission, callback) {
var isAllowedAsync = bluebird.promisify(isAllowed);
return isAllowedAsync(role, resource, permission).nodeify(callback);
};
However with this code, the callback is never executed. After some more research, I tried this:
this.isAllowed = function(role, resource, permission, callback) {
return new bluebird(function (resolve, reject) {
resolve(isAllowed(role, resource, permission));
}).nodeify(callback);
};
With that code, both the node callback and Promise API works.
For reference, this is the isAllowed method:
var isAllowed = function(role, resource, permission) {
if(!lists[role] || !lists[role][resource]) {
return false;
}
return lists[role][resource].indexOf(permission) !== -1;
};
Am I doing something wrong in the first code example or is the second example the real way of getting what I am looking for?
Share Improve this question edited May 7, 2014 at 8:20 Esailija 140k23 gold badges279 silver badges328 bronze badges asked May 6, 2014 at 17:26 ryanzecryanzec 28.1k39 gold badges116 silver badges173 bronze badges 1-
1
isAllowed
is a synchronous function, it makes no sense to do this – Esailija Commented May 7, 2014 at 8:09
1 Answer
Reset to default 13Your specific problem makes no sense (see my ment) so I'll just be generic. There are 2 ways to expose a dual promise/callback API.
First way is to have the same function support promises and callbacks at the same time, by returning a promise if callback parameter is not passed or using the callback if it is passed.
However this is hard to implement and can have some nasty problems when some arguments are optional.
To implement it, you do exactly the same thing as you would with a 100% promise function except you add a .nodeify
at the end of the returned chain.
// Note however this doesn't work if some arguments before
// `callback` are optional
function dualApi(..., callback) {
// acting as if you would never support callbacks at all
return getPromise()
.then(...)
.then(...)
.then(...)
// .nodeify at the end of the chain, NOWHERE else
.nodeify(callback)
}
The second way is to define a normal callback api, and then just call promisifyAll
. This is very easy to implement, in fact there is almost no reason to do it at all because the user can so easily promisify the module themselves if they use bluebird.