Search code examples
node.jspromisebluebird

promisifying an already promisified function with promisifyAll


According to Bluebird documentation about promisification:

If the object already has a promisified version of the method, it will be skipped.

In fact, the promisifyAll() also creates an Async version of an already promisified function, which is expected to be:

idempotent in the sense that promisified functions are instantly returned back.

As pointed in Issue Idempotent promisify #159

So in the following example, I was expecting that both obj.foo() and obj.fooAsync() have the same result.

let obj = {
    foo: function(){
        return Promise.resolve('I am foo!!!')
    }
}
obj = Promise.promisifyAll(obj)
obj.foo().then(msg => console.log(msg))      // > I am foo
obj.fooAsync().then(msg => console.log(msg)) // prints nothing

Which part am I misunderstanding?

Running example here


Solution

  • Which part am I misunderstanding?

    That your foo function would be promisified already. It's not - it just returns a promise. And as Petka points out, "It is impossible to tell in code if some function is a promise returning function." (at least in the general sense, there are some functions for which we can tell).

    Being "promisified", especially in the context of an idempotent Promise.promisify function, refers to a function that is the result of a Promise.promisify call (or was created through Promise.promisifyAll). It's about this part of the code that checks whether the function is tagged as being bluebird-created.

    A better demonstration:

    const obj = {
        foo(callback) {
            callback(null, 'I am foo!!!')
        }
    };
    Promise.promisifyAll(obj);
    obj.fooAsync().then(console.log) // > I am foo
    // so far so good
    
    Promise.promisifyAll(obj);
    console.assert(typeof obj.fooAsyncAsync == "undefined"); // it didn't promisify again
    console.assert(obj.fooAsync === Promise.promisify(obj.fooAsync));