Last Updated: February 25, 2016
·
2.255K
· phantom

Writing dynamic function patcher for REST api on angularjs service

In this example I'm showing you how i implement $rootScope.$apply() for each REST api call.
This is just example how you can extend your function callbacks if we assume that your REST api callback is always on last place of function.

/*** this is just example of some javascript api api ***/
this.api = {
    assets: {
        _init: function () {
            //do something here and this will not be patched
        },
        one: function (id, callback) {
            http({ data: {id: id}}).success(callback);
        },
        two: function (id, callback) {
            http({ data: {id: id}}).success(callback);
        }
    }
}

var that = this,
    /**
     * Don't include methods
     * @type {Array}
     */
        excludeMethods = [
        '_init',
        'option'
    ],
    patchObjects = [ 'assets', 'user'];

Api patcher extend the callback and put a $rootScope.$apply(); to each function callback

/**
 * Api patcher
 * @param source
 * @param destionation
 */
function extend(source, destionation) {
    var fn = function (i) {
        return function () {
            var lastIndex = arguments.length - 1,
                args = Array.prototype.slice.call(arguments, 0, lastIndex),
                callback = arguments[lastIndex];
            /**
             * Patch last one
             */
            args.push(function (data, error) {
                if (angular.isFunction(callback)) {
                    callback.call(this, data, error);
                    $rootScope.$apply();
                }
            });
            /**
             * Call the source with new arguments
             */
            source[i].apply(source, args);
        }
    };
    /**
     * Loop over method
     */
    for (var i in source) {
        if (excludeMethods.indexOf(i) === -1) {
            if (angular.isFunction(source[i])) {
                destionation[i] = fn(i);
            }
        }
    }
}

/**
 * Patch objects
 */
patchObjects.forEach(function (value) {
    that[value] = {}; // initialize
    extend(that.api[value], that[value]);
});

The service will have method like which you will call in controller

myApiService.assets.one(id, function (data, error) {
       $scope.list = data;
           // now you don't need to call $rootScope.$apply(); on each request
});