Created
April 24, 2014 12:32
-
-
Save bennadel/11253036 to your computer and use it in GitHub Desktop.
Aborting AJAX Requests Using $http And AngularJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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