Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapper function which returns promise irrespective of function arguments

In my project, I have a scenario where I have different kind of functions with different arguments. One of those arguments holds the callback function. And also there is a case where the function doesn't have any arguments. As shown below:

abc(string, function, number)
aaa(function, string)
bcd()
xyz(function)
cda(string, number, function, string)

I need to write a function such that irrespective of the irregularity of above functions, the function should return a promise.

Example:

// Assume $q has been injected
var defer = $q.defer();
function returnPromise(functionName, functionArgumentsInArray){
    defer.resolve(window[functionName].apply(null, functionArgumentsInArray));
    return defer.promise;
}

As you can see, the above function doesn't resolve the callback function but just the function.

Note: The functions will have max of one function argument or none.

I know it can be done individually for each case as follows:

function returnPromise(){
    var defer = $q.defer();
    abc("hey", function() {
        defer.resolve(arguments);
    }, 123);
    return defer.promise;
}

But I am looking for a common wrapper for all such functions.

like image 216
Mr_Green Avatar asked Jul 27 '26 07:07

Mr_Green


1 Answers

I think you are looking for something like

const cbPlaceholder = Symbol("placeholder for node callback");
function wrap(fn) {
    return function(...args) {
        return $q((resolve, reject) => {
            function nodeback(err, result) {
                if (err) reject(err);
                else resolve(result);
            }
            for (var i=0; i<args.length; i++)
                if (args[i] === cbPlaceholder) {
                    args[i] = nodeback;
                    break;
                }
            const res = fn.apply(this, args);
            if (i == args.length) // not found
                resolve(res);
        });
    };
}

You could use it as

const abcPromised = wrap(abc);
abcPromised("hey", cbPlaceholder, 123).then(…)

Also have a look at How do I convert an existing callback API to promises?. In general you should not need that placeholder thing when all promisified functions follow the convention to take the callback as their last parameter.

like image 116
Bergi Avatar answered Jul 29 '26 21:07

Bergi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!