Search code examples
javascriptangularjsangular-promiseangular-resource

service method does not recognize variable defined outside


Here is a service:

angular.module('core').factory('ServerErrorAlert', ['toaster',
    function(toaster) {
        return function(errorResponse) {
            toaster.pop('error', 'Error', errorResponse);
            if (deferred) {
                deferred.reject(errorResponse);
            }
        }
    }
]);

Here is how I call it :

function update(updatedTransaction, originalTransaction, updateLocal) {
            var deferred = $q.defer();
            updatedTransaction.$update(function() {
                if (updateLocal) {angular.extend(originalTransaction, updatedTransaction);}
                deferred.resolve(updateLocal ? originalTransaction : false);
            } , ServerErrorAlert);
            return deferred.promise;
        };

The second update function that is calling ServerErrorAlert is also a service. I would like for it to return a promise so that it can be chained.

As you can see ServerErrorAlert is merely a convenience function. I do not define deferred in the service, instead I was hoping that it would recognize it. However, this is not the case, deferred is not recognized by the service.

I guess I am just confused because if I replace the ServerErrorAlert argument in $update with the return value of the service, namely the function definition, I am confident that it would recognize deferred. Why does it not recognize it once the method is extracted?

Basically, I want ServerErrorAlert to handle all server errors arising from $resource calls but I do not want to keep copy and pasting the function definition as the error callback. Instead I was hoping to just paste one word in there (for code reuse).

How can I accomplish what I am trying to accomplish?

Thanks in advance.


Solution

  • Simply return a rejected promise, eg

    .factory('ServerErrorAlert', ['$q', 'toaster', function($q, toaster) {
        return function(errorResponse) {
            toaster.pop('error', 'Error', errorResponse);
            return $q.reject(errorResponse);
        }
    }]);
    

    I would also change the way you're resolving the resource promise. You don't really need to create your own deferred object. Try this instead...

    return updatedTransaction.$update().then(function() {
        if (updateLocal) { // assuming this is actually defined and in scope
            angular.extend(originalTransaction, updatedTransaction);
            return originalTransaction;
        }
        return false;
    }, ServerErrorAlert);