Skip to content

Commit 57d1a7b

Browse files
committed
Add cancel-promise demo.
1 parent 9544963 commit 57d1a7b

File tree

5 files changed

+254
-0
lines changed

5 files changed

+254
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ with.
1010

1111
## My JavaScript Demos - I Love JavaScript!
1212

13+
* [Canceling A Promise In AngularJS](http://bennadel.github.io/JavaScript-Demos/demos/cancel-promise-angularjs/)
1314
* [Multiple Isolate-Scopes Cannot Be Applied To The Same Element In AngularJS](http://bennadel.github.io/JavaScript-Demos/demos/multiple-isolate-scopes-angularjs/)
1415
* [Breaking Changes In Isolate-Scope Behavior In AngularJS 1.2](http://bennadel.github.io/JavaScript-Demos/demos/changes-in-isolate-scope-angularjs/)
1516
* [Isolate-Scope Attribute Expressions Use Dependency-Injection In AngularJS](http://bennadel.github.io/JavaScript-Demos/demos/isolate-scope-attribute-expression-di-angularjs/)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
component
2+
output = false
3+
hint = "I define the application settings and event handlers."
4+
{
5+
6+
// Define the application settings.
7+
this.name = hash( getCurrentTemplatePath() );
8+
this.applicationTimeout = createTimeSpan( 0, 0, 1, 0 );
9+
this.sessionManagement = false;
10+
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<cfscript>
2+
3+
// Sleep for 3-seconds to give our demo time to cancel the promise.
4+
sleep( 3 * 1000 );
5+
6+
friends = [
7+
{
8+
"id" = 1,
9+
"name" = "Sarah"
10+
},
11+
{
12+
"id" = 2,
13+
"name" = "Tricia"
14+
},
15+
{
16+
"id" = 3,
17+
"name" = "Kim"
18+
}
19+
];
20+
21+
responseBody = serializeJson( friends );
22+
23+
</cfscript>
24+
25+
<cfcontent
26+
type="application/x-json"
27+
variable="#charsetDecode( responseBody, 'utf-8' )#"
28+
/>
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
a[ ng-click ] {
3+
color: red ;
4+
cursor: pointer ;
5+
text-decoration: underline ;
6+
}
+208
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
<!doctype html>
2+
<html ng-app="Demo">
3+
<head>
4+
<meta charset="utf-8" />
5+
6+
<title>
7+
Canceling A Promise In AngularJS
8+
</title>
9+
10+
<link rel="stylesheet" type="text/css" href="./demo.css"></link>
11+
</head>
12+
<body ng-controller="AppController">
13+
14+
<h1>
15+
Canceling A Promise In AngularJS
16+
</h1>
17+
18+
<ul>
19+
<li ng-repeat="friend in friends">
20+
{{ friend.name }}
21+
</li>
22+
</ul>
23+
24+
<p>
25+
<a ng-click="reload()">Reload friends</a>
26+
</p>
27+
28+
29+
<!-- Load scripts. -->
30+
<script type="text/javascript" src="../../vendor/jquery/jquery-2.1.0.min.js"></script>
31+
<script type="text/javascript" src="../../vendor/angularjs/angular-1.2.26.min.js"></script>
32+
<script type="text/javascript">
33+
34+
// Create an application module for our demo.
35+
var app = angular.module( "Demo", [] );
36+
37+
38+
// -------------------------------------------------- //
39+
// -------------------------------------------------- //
40+
41+
42+
// I control the root of the application.
43+
app.controller(
44+
"AppController",
45+
function( $scope, friendService ) {
46+
47+
// I contain the list of friends to render.
48+
$scope.friends = [];
49+
50+
// When the scope is destroyed, we want to clean up the controller,
51+
// including canceling any outstanding request to gather friends.
52+
$scope.$on(
53+
"$destroy",
54+
function handleDestroyEvent() {
55+
56+
friendService.cancel( lastRequest );
57+
58+
}
59+
);
60+
61+
// Load the list of friends.
62+
var lastRequest = loadRemoteData();
63+
64+
65+
// ---
66+
// PUBLIC METHODS.
67+
// ---
68+
69+
70+
// I reload the list of friends.
71+
$scope.reload = function() {
72+
73+
loadRemoteData();
74+
75+
}
76+
77+
78+
// ---
79+
// PRIVATE METHODS.
80+
// ---
81+
82+
83+
// I load the remote friend data and return the request promise.
84+
function loadRemoteData() {
85+
86+
// Cancel any pending request for friends.
87+
// --
88+
// NOTE: This will not error if lastRequest is null or undefined.
89+
friendService.cancel( lastRequest );
90+
91+
// Make the request for friends. It's important that we save this
92+
// reference rather than the subsequent .then() result as this is
93+
// the one that can be "canceled". The subsequent .then() result
94+
// cannot be canceled as it is an entirely different promise.
95+
lastRequest = friendService.getFriends();
96+
97+
lastRequest.then(
98+
function handleGetFriendsResolve( friends ) {
99+
100+
$scope.friends = friends;
101+
102+
},
103+
function handleGetFriendsReject( error ) {
104+
105+
// The request failed or was CANCELED.
106+
console.warn( "Friends error:" );
107+
console.log( error );
108+
109+
}
110+
);
111+
112+
return( lastRequest );
113+
114+
}
115+
116+
}
117+
);
118+
119+
120+
// -------------------------------------------------- //
121+
// -------------------------------------------------- //
122+
123+
124+
// I provide access to the Friends repository.
125+
app.service(
126+
"friendService",
127+
function( $http, $q ) {
128+
129+
// Return the public API.
130+
return({
131+
cancel: cancel,
132+
getFriends: getFriends
133+
});
134+
135+
136+
// ---
137+
// PUBLIC METHODS.
138+
// ---
139+
140+
141+
// I cancel the underlying AJAX request associated with the given promise.
142+
// If the promise has not yet been resolved, this will cause the promise
143+
// to be rejected with status:0.
144+
// --
145+
// NOTE: This will NOT raise an exception if the promise is invalid or
146+
// already resolved / rejected.
147+
function cancel( promise ) {
148+
149+
// If the promise does not contain a hook into the deferred timeout,
150+
// the simply ignore the cancel request.
151+
if (
152+
promise &&
153+
promise._httpTimeout &&
154+
promise._httpTimeout.resolve
155+
) {
156+
157+
promise._httpTimeout.resolve();
158+
159+
}
160+
161+
}
162+
163+
164+
// I get the full list of friends, returns a promise.
165+
function getFriends() {
166+
167+
var httpTimeout = $q.defer();
168+
169+
// When making the HTTP request, pass in the promise for our deferred
170+
// timeout. If the deferred timeout is ever resolved, the underlying
171+
// AJAX request will be aborted (if not already).
172+
var request = $http({
173+
method: "get",
174+
url: "./api/index.cfm",
175+
timeout: httpTimeout.promise
176+
});
177+
178+
var promise = request.then( unwrapResolve );
179+
180+
// Store the deferred timeout on the promise so that our .cancel()
181+
// method can access it later, if necessary.
182+
promise._httpTimeout = httpTimeout;
183+
184+
return( promise );
185+
186+
}
187+
188+
189+
// ---
190+
// PRIVATE METHODS.
191+
// ---
192+
193+
194+
// I unwrap the AngularJS $http response, extracting the data from the
195+
// more robust response object.
196+
function unwrapResolve( response ) {
197+
198+
return( response.data );
199+
200+
}
201+
202+
}
203+
);
204+
205+
</script>
206+
207+
</body>
208+
</html>

0 commit comments

Comments
 (0)