Search code examples
angularjsangularjs-scopengcordova

How does one use functions designed with callbacks within an AngularJS promise?


If a Javascript function is designed with callbacks, how does one encapsulate that function within an AngularJS promise?

For example, I am looking at using the following Cordova plugin: cordova.plugins.diagnostic (see https://www.npmjs.com/package/cordova.plugins.diagnostic). Many of its functions are designed with callbacks. Because the requests are engaging the device's OS, it may take a little time before a function completes, so I'm considering whether they should be called within a promise structure. For example, how would one convert the following:

cordova.plugins.diagnostic.isWifiEnabled(function(enabled){
    <do something>
}, function(error){
    <do something>
});

or really any generic callback structure...

masterFunction(function(enabled){
    <do something>
}, function(error){
    <do something>
});

to operate within an AngularJS promise? Would it be something like this?

function callMasterFunction() {
    var deferred = $q.defer();

    masterFunction(function(enabled){
        <do something>
        deferred.resolve(enabled);
    }, function(error){
        <do something>
        deferred.resolve(error);
    });

    return deferred.promise;
}

I would think that this would also be a concern when using AngularJS with Cordova and the W3C Geolocation APIs. It seems to me that I may not have a clear picture of how the scope is being managed in these cases.

Ultimately, I can see chaining many of these sorts of calls together. Something like:

var promise = callMasterFunction1()
.then(function(response) { return callMasterFunction2(); })
.then(function(response) { return callMasterFunction3(); })
...

Any help would be appreciated. Thank you for your time.


Solution

  • You can use the promise constructor to create a promise from a callback-based API:

    function callMasterFunction() {
        return $q(function (resolve, reject) {
            cordova.plugins.diagnostic.isWifiEnabled(resolve, reject);
        });
    }
    

    Now callMasterFunction() returns a promise:

    callMasterFunction()
        .then(function (enabled) {
            console.log('Wifi is ' + (enabled ? '' : 'not ') + 'enabled.');
        })
        .catch(function (error) {
            console.error('Something went wrong: ', error);
        });
    

    And when you want to chain them, you can do this:

    var promise = callMasterFunction1()
        .then(callMasterFunction2)
        .then(callMasterFunction3);