Abort AngularJS $http request, deeply nested in multiple service calls

Joel

I'm using a deferred promise to abort a $http request (like explained in this post).

However, I'm unsure of how I should propagate the abort() function added at the root level. Everytime I call .then() on the promise, a new promise (without the abort() function) is returned.

See my example below. I have a controller calling a service, that in turn calls another service (where the $http request is made). The example does not work, since promise in MyController is not the same as the one that was returned in restService, and therefore does not have a function called abort().

  1. How can I propagate the abort() function so that it is available in MyController?
  2. Can I return the original promise all the way, and just call then() on that (like in the examples at the bottom)?. What happens with the then() calls? Are they still invoked "synchronously"?

Controller

app.controller("MyController", function($scope, dataService) {
    var promise;

    $scope.loadAndAbortData = function () {
        promise = dataService.getData().then(updateUI);
    };

    $scope.abort = function () {
        if (promise) {
            promise.abort();
        }
    };
}

DataService

app.service("dataService", function(restService) {
    var service = {
        getData: function () {
            return restService.get().then(function (response) {
                var modifiedData = modifyData(response.data);
                return modifiedData;
            }, function (response) {
                handleError(response.data);
                $q.reject(response.data);
            });               
        };
    };

    return service;
}

RestService:

app.service("restService", function($http, $q) {
    var service = {
        get: function () {
            var deferredAbort = $q.defer();
            var request = $http.get(url, { timeout: deferredAbort.promise } );

            promise.abort = function () {
                deferredAbort.resolve();
            }

            return promise;
        };
    };

    return service;
}

Is this a solution for DataService and MyController?

app.controller("MyController", function($scope, dataService) {
    var promise;

    $scope.loadAndAbortData = function () {
        promise = dataService.getData();
        promise.then(updateUI);
    };

    $scope.abort = function () {
        if (promise) {
            promise.abort();
        }
    };
}

app.service("dataService", function(restService) {
    var service = {
        getData: function () {
            var promise = restService.get();
            promise.then(function (response) {
                var modifiedData = modifyData(response.data);
                return modifiedData;
            }, function (response) {
                handleError(response.data);
                $q.reject(response.data);
            });

            return promise;           
        };
    };

    return service;
}
Joel

I ended up with a solution that "overrides" the then() function of the promise, so that the abort() function will follow along through all the layers, independent of how many times then()/catch()/finally() is called on the promise.

I would really appreciate some input, if someones finds a better solution or sees flaws in this one.

app.service("restService", function($http, $q) {

    function createAbortablePromise(promise, deferredAbort) {
        promise.abort = function () {
            deferredAbort.resolve();
        };

        // A problem with adding the abort function to the promise is that as soon as someone
        // calls then() on this promise (somewhere else in our application), another new promise
        // is returned. This new promise, will not have the abort() function. We can solve this
        // by "overriding" then() recursively.
        var originalThen = promise.then;
        promise.then = function (callback, errback, progressback) {
            // Invoke the original then(). It will return a new promise
            var newPromise = originalThen(callback, errback, progressback);

            // This new promise needs an abort function as well.
            newPromise = createAbortablePromise(newPromise, deferredAbort);

            return newPromise;
        };

        return promise;
    }

    var service = {
        get: function () {
            var deferredAbort = $q.defer();
            var request = $http.get(url, { timeout: deferredAbort.promise } );

            promise.abort = function () {
                deferredAbort.resolve();
            }

            promise = createAbortablePromise(promise, deferredAbort);

            return promise;
        };
    };

    return service;
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

AngularJs : Multiple Calls for $http service

Multiple $http calls in AngularJS

Indenting deeply nested function calls

AngularJS $http request inside service

AngularJS Function After Multiple Async Service Calls

make multiple http calls synchronously in AngularJs

Avoid deeply nested function calls Pythonically

Alternative to deeply nested function calls or events

Make nested HTTP calls from a Service Class and return Observable

Angular nested service calls

AngularJS service that uses multiple $http.get

Posting multiple arrays with $http service in AngularJS

AngularJS rendering from deeply nested jsonp

Updating deeply nested models with rails and angularjs

Forward request headers to multiple service calls in Spring + Netflix + Feign

AngularJS REST service calls

Is there standard way of making multiple API calls combined into one HTTP request?

Angularjs - Combining data from multiple $http calls in a for loop

Angularjs - Multiple $http REST calls (second call dependent on output of first)

AngularJs directive and $http calls

How to abort an HTTP Request from .NET?

How to abort/cancel HTTP request in Python thread?

AngularJS - Cancelling a HTTP Request From a Service That Returns a Promise

Send array via GET request with AngularJS' $http service

Angularjs, Directive use a service which make a http request first

Abort a multiple file upload AJAX request

Node. js Nested async map with multiple http request

How can I make multiple nested http request in RxJs?

Preventing Multiple http calls