@@ -40,6 +40,8 @@ function Browser(window, document, body, XHR, $log) {
4040 rawDocument = document [ 0 ] ,
4141 location = window . location ,
4242 setTimeout = window . setTimeout ,
43+ clearTimeout = window . clearTimeout ,
44+ pendingDeferIds = { } ,
4345 lastLocationUrl ;
4446
4547 self . isMock = false ;
@@ -163,15 +165,12 @@ function Browser(window, document, body, XHR, $log) {
163165 * @returns {function() } the added function
164166 */
165167 self . addPollFn = function ( fn ) {
166- if ( ! pollTimeout ) startPoller ( 100 , setTimeout ) ;
168+ if ( isUndefined ( pollTimeout ) ) startPoller ( 100 , setTimeout ) ;
167169 pollFns . push ( fn ) ;
168170 return fn ;
169171 } ;
170172
171173 /**
172- * @name angular.service.$browser#startPoller
173- * @methodOf angular.service.$browser
174- *
175174 * @param {number } interval How often should browser call poll functions (ms)
176175 * @param {function() } setTimeout Reference to a real or fake `setTimeout` function.
177176 *
@@ -339,20 +338,49 @@ function Browser(window, document, body, XHR, $log) {
339338 * @methodOf angular.service.$browser
340339 * @param {function() } fn A function, who's execution should be defered.
341340 * @param {number= } [delay=0] of milliseconds to defer the function execution.
341+ * @returns {* } DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
342342 *
343343 * @description
344344 * Executes a fn asynchroniously via `setTimeout(fn, delay)`.
345345 *
346346 * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
347- * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed via
348- * `$browser.defer.flush()`.
347+ * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
348+ * via `$browser.defer.flush()`.
349349 *
350350 */
351351 self . defer = function ( fn , delay ) {
352+ var timeoutId ;
352353 outstandingRequestCount ++ ;
353- setTimeout ( function ( ) { completeOutstandingRequest ( fn ) ; } , delay || 0 ) ;
354+ timeoutId = setTimeout ( function ( ) {
355+ delete pendingDeferIds [ timeoutId ] ;
356+ completeOutstandingRequest ( fn ) ;
357+ } , delay || 0 ) ;
358+ pendingDeferIds [ timeoutId ] = true ;
359+ return timeoutId ;
354360 } ;
355361
362+
363+ /**
364+ * @workInProgress
365+ * @ngdoc method
366+ * @name angular.service.$browser.defer#cancel
367+ * @methodOf angular.service.$browser.defer
368+ * @returns {boolean } Returns `true` if the task hasn't executed yet and was successfuly canceled.
369+ *
370+ * @description
371+ * Cancels a defered task identified with `deferId`.
372+ */
373+
374+ self . defer . cancel = function ( deferId ) {
375+ if ( pendingDeferIds [ deferId ] ) {
376+ delete pendingDeferIds [ deferId ] ;
377+ clearTimeout ( deferId ) ;
378+ completeOutstandingRequest ( noop ) ;
379+ return true ;
380+ }
381+ } ;
382+
383+
356384 //////////////////////////////////////////////////////////////
357385 // Misc API
358386 //////////////////////////////////////////////////////////////
0 commit comments