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()
.
abort()
function so that it is available in MyController
?then()
on that (like in the examples at the bottom)?. What happens with the then()
calls? Are they still invoked "synchronously"?app.controller("MyController", function($scope, dataService) {
var promise;
$scope.loadAndAbortData = function () {
promise = dataService.getData().then(updateUI);
};
$scope.abort = function () {
if (promise) {
promise.abort();
}
};
}
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;
}
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;
}
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;
}
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.
Comments