23
23
* @param {object } $sniffer $sniffer service
24
24
*/
25
25
function Browser ( window , document , $log , $sniffer ) {
26
+ var ALL_TASKS_TYPE = '$$all$$' ,
27
+ DEFAULT_TASK_TYPE = '$$default$$' ;
28
+
26
29
var self = this ,
27
30
location = window . location ,
28
31
history = window . history ,
29
32
setTimeout = window . setTimeout ,
30
33
clearTimeout = window . clearTimeout ,
31
- pendingDeferIds = { } ;
34
+ pendingDeferIds = { } ,
35
+ outstandingRequestCounts = { } ,
36
+ outstandingRequestCallbacks = [ ] ;
32
37
33
38
self . isMock = false ;
34
39
35
- var outstandingRequestCount = 0 ;
36
- var outstandingRequestCallbacks = [ ] ;
37
-
38
40
// TODO(vojta): remove this temporary api
39
41
self . $$completeOutstandingRequest = completeOutstandingRequest ;
40
- self . $$incOutstandingRequestCount = function ( ) { outstandingRequestCount ++ ; } ;
42
+ self . $$incOutstandingRequestCount = incOutstandingRequestCount ;
41
43
42
44
/**
43
- * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
44
- * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
45
+ * Executes the `fn` function and decrements the appropriate `outstandingRequestCounts` counter.
46
+ * If the counter reaches 0, all the corresponding `outstandingRequestCallbacks` are executed.
47
+ * @param {Function } fn - The function to execute.
48
+ * @param {string= } [taskType=DEFAULT_TASK_TYPE] The type of task that is being completed.
45
49
*/
46
- function completeOutstandingRequest ( fn ) {
50
+ function completeOutstandingRequest ( fn , taskType ) {
51
+ taskType = taskType || DEFAULT_TASK_TYPE ;
47
52
try {
48
- fn . apply ( null , sliceArgs ( arguments , 1 ) ) ;
53
+ fn ( ) ;
49
54
} finally {
50
- outstandingRequestCount -- ;
51
- if ( outstandingRequestCount === 0 ) {
52
- while ( outstandingRequestCallbacks . length ) {
55
+ decOutstandingRequestCount ( taskType ) ;
56
+
57
+ var countForType = outstandingRequestCounts [ taskType ] ;
58
+ var countForAll = outstandingRequestCounts [ ALL_TASKS_TYPE ] ;
59
+
60
+ // If at least one of the queues (`ALL_TASKS_TYPE` or `taskType`) is empty, run callbacks.
61
+ if ( ! countForAll || ! countForType ) {
62
+ var getNextCallback = ! countForAll ? getLastCallback : getLastCallbackForType ;
63
+ var nextCb ;
64
+
65
+ while ( ( nextCb = getNextCallback ( taskType ) ) ) {
53
66
try {
54
- outstandingRequestCallbacks . pop ( ) ( ) ;
67
+ nextCb ( ) ;
55
68
} catch ( e ) {
56
69
$log . error ( e ) ;
57
70
}
@@ -60,6 +73,33 @@ function Browser(window, document, $log, $sniffer) {
60
73
}
61
74
}
62
75
76
+ function decOutstandingRequestCount ( taskType ) {
77
+ taskType = taskType || DEFAULT_TASK_TYPE ;
78
+ if ( outstandingRequestCounts [ taskType ] ) outstandingRequestCounts [ taskType ] -- ;
79
+ if ( outstandingRequestCounts [ ALL_TASKS_TYPE ] ) outstandingRequestCounts [ ALL_TASKS_TYPE ] -- ;
80
+ }
81
+
82
+ function incOutstandingRequestCount ( taskType ) {
83
+ taskType = taskType || DEFAULT_TASK_TYPE ;
84
+ outstandingRequestCounts [ taskType ] = ( outstandingRequestCounts [ taskType ] || 0 ) + 1 ;
85
+ outstandingRequestCounts [ ALL_TASKS_TYPE ] = ( outstandingRequestCounts [ ALL_TASKS_TYPE ] || 0 ) + 1 ;
86
+ }
87
+
88
+ function getLastCallback ( ) {
89
+ var cbInfo = outstandingRequestCallbacks . pop ( ) ;
90
+ return cbInfo && cbInfo . cb ;
91
+ }
92
+
93
+ function getLastCallbackForType ( taskType ) {
94
+ for ( var i = outstandingRequestCallbacks . length - 1 ; i >= 0 ; -- i ) {
95
+ var cbInfo = outstandingRequestCallbacks [ i ] ;
96
+ if ( cbInfo . type === taskType ) {
97
+ outstandingRequestCallbacks . splice ( i , 1 ) ;
98
+ return cbInfo . cb ;
99
+ }
100
+ }
101
+ }
102
+
63
103
function getHash ( url ) {
64
104
var index = url . indexOf ( '#' ) ;
65
105
return index === - 1 ? '' : url . substr ( index ) ;
@@ -68,13 +108,15 @@ function Browser(window, document, $log, $sniffer) {
68
108
/**
69
109
* @private
70
110
* TODO(vojta): prefix this method with $$ ?
71
- * @param {function() } callback Function that will be called when no outstanding request
111
+ * @param {function() } callback Function that will be called when no outstanding request.
112
+ * @param {string= } [taskType=ALL_TASKS_TYPE] The type of tasks that will be waited for.
72
113
*/
73
- self . notifyWhenNoOutstandingRequests = function ( callback ) {
74
- if ( outstandingRequestCount === 0 ) {
114
+ self . notifyWhenNoOutstandingRequests = function ( callback , taskType ) {
115
+ taskType = taskType || ALL_TASKS_TYPE ;
116
+ if ( ! outstandingRequestCounts [ taskType ] ) {
75
117
callback ( ) ;
76
118
} else {
77
- outstandingRequestCallbacks . push ( callback ) ;
119
+ outstandingRequestCallbacks . push ( { type : taskType , cb : callback } ) ;
78
120
}
79
121
} ;
80
122
@@ -307,7 +349,8 @@ function Browser(window, document, $log, $sniffer) {
307
349
/**
308
350
* @name $browser#defer
309
351
* @param {function() } fn A function, who's execution should be deferred.
310
- * @param {number= } [delay=0] of milliseconds to defer the function execution.
352
+ * @param {number= } [delay=0] Number of milliseconds to defer the function execution.
353
+ * @param {string= } [taskType=DEFAULT_TASK_TYPE] The type of task that is deferred.
311
354
* @returns {* } DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
312
355
*
313
356
* @description
@@ -318,14 +361,19 @@ function Browser(window, document, $log, $sniffer) {
318
361
* via `$browser.defer.flush()`.
319
362
*
320
363
*/
321
- self . defer = function ( fn , delay ) {
364
+ self . defer = function ( fn , delay , taskType ) {
322
365
var timeoutId ;
323
- outstandingRequestCount ++ ;
366
+
367
+ delay = delay || 0 ;
368
+ taskType = taskType || DEFAULT_TASK_TYPE ;
369
+
370
+ incOutstandingRequestCount ( taskType ) ;
324
371
timeoutId = setTimeout ( function ( ) {
325
372
delete pendingDeferIds [ timeoutId ] ;
326
- completeOutstandingRequest ( fn ) ;
327
- } , delay || 0 ) ;
328
- pendingDeferIds [ timeoutId ] = true ;
373
+ completeOutstandingRequest ( fn , taskType ) ;
374
+ } , delay ) ;
375
+ pendingDeferIds [ timeoutId ] = taskType ;
376
+
329
377
return timeoutId ;
330
378
} ;
331
379
@@ -341,10 +389,11 @@ function Browser(window, document, $log, $sniffer) {
341
389
* canceled.
342
390
*/
343
391
self . defer . cancel = function ( deferId ) {
344
- if ( pendingDeferIds [ deferId ] ) {
392
+ if ( pendingDeferIds . hasOwnProperty ( deferId ) ) {
393
+ var taskType = pendingDeferIds [ deferId ] ;
345
394
delete pendingDeferIds [ deferId ] ;
346
395
clearTimeout ( deferId ) ;
347
- completeOutstandingRequest ( noop ) ;
396
+ completeOutstandingRequest ( noop , taskType ) ;
348
397
return true ;
349
398
}
350
399
return false ;
0 commit comments