Skip to content

@bennadel /abort-angularjs.htm
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Aborting AJAX Requests Using $http And AngularJS
<!doctype html>
<html ng-app="Demo">
<head>
<meta charset="utf-8" />
<title>
Aborting AJAX Requests Using $http And AngularJS
</title>
<style type="text/css">
a[ ng-click ] {
color: red ;
cursor: pointer ;
text-decoration: underline ;
}
</style>
</head>
<body ng-controller="DemoController">
<h1>
Aborting AJAX Requests Using $http And AngularJS
</h1>
<p>
<a ng-click="loadData()">Load Data</a> -
<a ng-click="abortRequest()">Abort Request</a>
</p>
<!-- Show when data is loading. -->
<p ng-if="isLoading">
<em>Loading...</em>
</p>
<!-- Show when data has finished loading. -->
<ul ng-if="! isLoading">
<li ng-repeat="friend in friends">
{{ friend.name }}
</li>
</ul>
<!-- Initialize scripts. -->
<script type="text/javascript" src="../jquery/jquery-2.1.0.min.js"></script>
<script type="text/javascript" src="../angularjs/angular-1.2.4.min.js"></script>
<script type="text/javascript">
// Define the module for our AngularJS application.
var app = angular.module( "Demo", [] );
// -------------------------------------------------- //
// -------------------------------------------------- //
// I control the main demo.
app.controller(
"DemoController",
function( $scope, friendService ) {
// I determine if remote data is currently being loaded.
$scope.isLoading = false;
// I contain the data that we wan to render.
$scope.friends = [];
// I hold the handle on the current request for data. Since we want to
// be able to abort the request, mid-stream, we need to hold onto the
// request which will have the .abort() method on it.
var requestForFriends = null;
// ---
// PUBLIC METHODS.
// ---
// I abort the current request (if its running).
$scope.abortRequest = function() {
return( requestForFriends && requestForFriends.abort() );
};
// I load the remote data for the view.
$scope.loadData = function() {
// Flag the data is currently being loaded.
$scope.isLoading = true;
$scope.friends = [];
// Make a request for data. Note that we are saving a reference to
// this response rather than just piping it directly into a .then()
// call. This is because we need to be able to access the .abort()
// method on the request and we'll lose that original reference after
// we call the .then() method.
( requestForFriends = friendService.getFriends() ).then(
function( newFriends ) {
// Flag the data as loaded.
$scope.isLoading = false;
$scope.friends = newFriends;
},
function( errorMessage ) {
// Flag the data as loaded (or rather, done trying to load). loading).
$scope.isLoading = false;
console.warn( "Request for friends was rejected." );
console.info( "Error:", errorMessage );
}
);
};
}
);
// -------------------------------------------------- //
// -------------------------------------------------- //
// I am the friend repository.
app.service(
"friendService",
function( $http, $q ) {
// I get the list of friends from the remote server.
function getFriends() {
// The timeout property of the http request takes a deferred value
// that will abort the underying AJAX request if / when the deferred
// value is resolved.
var deferredAbort = $q.defer();
// Initiate the AJAX request.
var request = $http({
method: "get",
url: "./api/friends.cfm",
timeout: deferredAbort.promise
});
// Rather than returning the http-promise object, we want to pipe it
// through another promise so that we can "unwrap" the response
// without letting the http-transport mechansim leak out of the
// service layer.
var promise = request.then(
function( response ) {
return( response.data );
},
function( response ) {
return( $q.reject( "Something went wrong" ) );
}
);
// Now that we have the promise that we're going to return to the
// calling context, let's augment it with the abort method. Since
// the $http service uses a deferred value for the timeout, then
// all we have to do here is resolve the value and AngularJS will
// abort the underlying AJAX request.
promise.abort = function() {
deferredAbort.resolve();
};
// Since we're creating functions and passing them out of scope,
// we're creating object references that may be hard to garbage
// collect. As such, we can perform some clean-up once we know
// that the requests has finished.
promise.finally(
function() {
console.info( "Cleaning up object references." );
promise.abort = angular.noop;
deferredAbort = request = promise = null;
}
);
return( promise );
}
// Return the public API.
return({
getFriends: getFriends
});
}
);
</script>
</body>
</html>
@mato75

it does not work for me, also tried http://developer.rackspace.com/blog/cancelling-ajax-requests-in-angularjs-applications.html and the request is not aborted.

using $resource

    var c$resource = $resource,
          c$q = $q;
    function _createResourceInstance(aborter) {
        return c$resource(
            'url', { 'q': '@q' },
            {
                fetch: {
                    method: 'JSONP',
                    params: { 'q': '@q' },
                    timeout: aborter.promise
                }
            }
        );
    }

    function resourceReport2() {
        var aborter = c$q.defer();

        // Initiate the AJAX request.
        var resource = _createResourceInstance(aborter);

        return {
            getResource: function () {
                console.log(resource)
                return resource;
            },
            /**
             * Recreates the resource instance.
             */
            renew: function () {
                aborter = c$q.defer();
                resource = _createResourceInstance(aborter);
            },
            /**
             * Aborts current requests and recreate abortable resource.
             */
            abort: function () {
                aborter.resolve();
                this.renew();
            }
        };

    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.