Mr_Green
Mr_Green

Reputation: 41832

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.

Upvotes: 3

Views: 980

Answers (1)

Bergi
Bergi

Reputation: 664650

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.

Upvotes: 3

Related Questions