I'm having trouble getting the Bluebird library's promisifyAll
function to work with an ES2015 class's object instance methods when arguments are omitted. I'm using Node 7.8.0. Here's some sample code:
// dog.js
class Dog {
constructor(opts) {
this.name = opts.name || 'Fido';
}
fetchBone(bone, callback) {
console.log('fetching the bone');
callback(null, 'got it');
}
}
exports = module.exports = Dog;
Let's say the bone is an optional argument for fetchBone
. When I pass it, everything's fine.
> var Dog = require('./dog');
> Promise = require('bluebird');
> Promise.promisifyAll(Dog); // omitting this line doesn't help
> Promise.promisifyAll(Dog.prototype);
> var puppy = new Dog();
> puppy.fetchBoneAsync('juicy bone')
.then(result => console.log('from promise:', result))
.catch(err => console.error('failure:', err));
fetching the bone
Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined }
> from promise: got it
It fails when I don't pass in the bone.
> puppy.fetchBoneAsync()
.then(result => console.log('from promise:', result))
.catch(err => console.error('failure:', err));
fetching the bone
Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined }
> failure: TypeError: callback is not a function
at Dog.fetchBone (dog.js:8:5)
at Dog.tryCatcher (node_modules/bluebird/js/release/util.js:16:23)
at Dog.ret [as fetchBoneAsync] (eval at makeNodePromisifiedEval (node_modules/bluebird/js/release/promisify.js:184:12), <anonymous>:14:23)
at repl:1:7
at ContextifyScript.Script.runInThisContext (vm.js:23:33)
at REPLServer.defaultEval (repl.js:339:29)
at bound (domain.js:280:14)
at REPLServer.runBound [as eval] (domain.js:293:12)
at REPLServer.onLine (repl.js:536:10)
at emitOne (events.js:101:20)
at REPLServer.emit (events.js:191:7)
at REPLServer.Interface._onLine (readline.js:241:10)
at REPLServer.Interface._line (readline.js:590:8)
at REPLServer.Interface._ttyWrite (readline.js:869:14)
at REPLServer.self._ttyWrite (repl.js:609:7)
at ReadStream.onkeypress (readline.js:120:10)
Strangely, it works if I pass in undefined
for the bone.
> puppy.fetchBoneAsync(undefined)
.then(result => console.log('from promise:', result))
.catch(err => console.error('failure:', err));
fetching the bone
Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined }
> from promise: got it
Anybody know what's going on here?
Yep, that is correct behavior. The promises are mapped to the original functions. So fetchBone()
is receiving two arguments in the first call and one in the second example.
This means that in the second example, when fetchBone()
is called callback
is undefined and the bone
itself is the callback function created by the promisification to handle the promise itself.