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