Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bluebird promisify and callback with no error argument

I'm trying to promisify a 3rd party library that doesn't use the callback(err, data) pattern. Instead they always return callback(data) and throw on errors.

Promise.promisifyAll(horse);

var p = Promise.defer();
horse.drinkAsync()
    .error(function(data)
    {
        p.fulfill(data);
    })
    .catch(function (err)
    {
        console.error('error occured', err);
    });

return p.promise;

What is a nice way to wrap such a behavior with promises and still have it look ok and allow to catch the thrown error? The catch clause doesn't trigger and the application crashes.

like image 699
Madd0g Avatar asked Jun 12 '14 22:06

Madd0g


People also ask

How do you Promisify a callback function?

To convert a callback into a promise, you need to return a promise. You run the code with the callback inside the promise. const readFilePromise = () => { return new Promise((resolve, reject) => { fs. readFile(filePath, options, (err, data) => { // ... }) }) }

What does Promisify mean?

promisify() method basically takes a function as an input that follows the common Node. js callback style, i.e., with a (err, value) and returns a version of the same that returns a promise instead of a callback.

How do you convert an existing callback API to promises?

If the callback function returns non-error output, we resolve the Promise with the output. Let's start by converting a callback to a promise for a function that accepts a fixed number of parameters: const fs = require('fs'); const readFile = (fileName, encoding) => { return new Promise((resolve, reject) => { fs.

What does promise Promisify do?

promisify. Returns a function that will wrap the given nodeFunction . Instead of taking a callback, the returned function will return a promise whose fate is decided by the callback behavior of the given node function.


1 Answers

From Bluebird 2.1 on, you can now customize promisifyAll with a custom promisification handler:

function noErrPromisifier(originalMethod){
    return function promisified() {
         var args = [].slice.call(arguments); // might want to use smarter
         var self = this                      // promisification if performance critical
         return new Promise(function(resolve,reject){
             args.push(resolve); 
             originalMethod.apply(self,args); // call with arguments
         });
    };
}

var horse = Promise.promisifyAll(require("horse"), {
    promisifier: noErrPromisifier
});

horse.drinkAsync().then(function(data){
     // Can use here, ow promisified normally.
});

If the original method throws asynchronously, there is really no way around wrapping it in a domain, although I've never seen a library that acts that poorly.

like image 123
Benjamin Gruenbaum Avatar answered Sep 18 '22 16:09

Benjamin Gruenbaum