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,35 @@ 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 ] ) {
79
+ outstandingRequestCounts [ taskType ] -- ;
80
+ outstandingRequestCounts [ ALL_TASKS_TYPE ] -- ;
81
+ }
82
+ }
83
+
84
+ function incOutstandingRequestCount ( taskType ) {
85
+ taskType = taskType || DEFAULT_TASK_TYPE ;
86
+ outstandingRequestCounts [ taskType ] = ( outstandingRequestCounts [ taskType ] || 0 ) + 1 ;
87
+ outstandingRequestCounts [ ALL_TASKS_TYPE ] = ( outstandingRequestCounts [ ALL_TASKS_TYPE ] || 0 ) + 1 ;
88
+ }
89
+
90
+ function getLastCallback ( ) {
91
+ var cbInfo = outstandingRequestCallbacks . pop ( ) ;
92
+ return cbInfo && cbInfo . cb ;
93
+ }
94
+
95
+ function getLastCallbackForType ( taskType ) {
96
+ for ( var i = outstandingRequestCallbacks . length - 1 ; i >= 0 ; -- i ) {
97
+ var cbInfo = outstandingRequestCallbacks [ i ] ;
98
+ if ( cbInfo . type === taskType ) {
99
+ outstandingRequestCallbacks . splice ( i , 1 ) ;
100
+ return cbInfo . cb ;
101
+ }
102
+ }
103
+ }
104
+
63
105
function getHash ( url ) {
64
106
var index = url . indexOf ( '#' ) ;
65
107
return index === - 1 ? '' : url . substr ( index ) ;
@@ -68,13 +110,15 @@ function Browser(window, document, $log, $sniffer) {
68
110
/**
69
111
* @private
70
112
* TODO(vojta): prefix this method with $$ ?
71
- * @param {function() } callback Function that will be called when no outstanding request
113
+ * @param {function() } callback Function that will be called when no outstanding request.
114
+ * @param {string= } [taskType=ALL_TASKS_TYPE] The type of tasks that will be waited for.
72
115
*/
73
- self . notifyWhenNoOutstandingRequests = function ( callback ) {
74
- if ( outstandingRequestCount === 0 ) {
116
+ self . notifyWhenNoOutstandingRequests = function ( callback , taskType ) {
117
+ taskType = taskType || ALL_TASKS_TYPE ;
118
+ if ( ! outstandingRequestCounts [ taskType ] ) {
75
119
callback ( ) ;
76
120
} else {
77
- outstandingRequestCallbacks . push ( callback ) ;
121
+ outstandingRequestCallbacks . push ( { type : taskType , cb : callback } ) ;
78
122
}
79
123
} ;
80
124
@@ -307,7 +351,8 @@ function Browser(window, document, $log, $sniffer) {
307
351
/**
308
352
* @name $browser#defer
309
353
* @param {function() } fn A function, who's execution should be deferred.
310
- * @param {number= } [delay=0] of milliseconds to defer the function execution.
354
+ * @param {number= } [delay=0] Number of milliseconds to defer the function execution.
355
+ * @param {string= } [taskType=DEFAULT_TASK_TYPE] The type of task that is deferred.
311
356
* @returns {* } DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
312
357
*
313
358
* @description
@@ -318,14 +363,19 @@ function Browser(window, document, $log, $sniffer) {
318
363
* via `$browser.defer.flush()`.
319
364
*
320
365
*/
321
- self . defer = function ( fn , delay ) {
366
+ self . defer = function ( fn , delay , taskType ) {
322
367
var timeoutId ;
323
- outstandingRequestCount ++ ;
368
+
369
+ delay = delay || 0 ;
370
+ taskType = taskType || DEFAULT_TASK_TYPE ;
371
+
372
+ incOutstandingRequestCount ( taskType ) ;
324
373
timeoutId = setTimeout ( function ( ) {
325
374
delete pendingDeferIds [ timeoutId ] ;
326
- completeOutstandingRequest ( fn ) ;
327
- } , delay || 0 ) ;
328
- pendingDeferIds [ timeoutId ] = true ;
375
+ completeOutstandingRequest ( fn , taskType ) ;
376
+ } , delay ) ;
377
+ pendingDeferIds [ timeoutId ] = taskType ;
378
+
329
379
return timeoutId ;
330
380
} ;
331
381
@@ -341,10 +391,11 @@ function Browser(window, document, $log, $sniffer) {
341
391
* canceled.
342
392
*/
343
393
self . defer . cancel = function ( deferId ) {
344
- if ( pendingDeferIds [ deferId ] ) {
394
+ if ( pendingDeferIds . hasOwnProperty ( deferId ) ) {
395
+ var taskType = pendingDeferIds [ deferId ] ;
345
396
delete pendingDeferIds [ deferId ] ;
346
397
clearTimeout ( deferId ) ;
347
- completeOutstandingRequest ( noop ) ;
398
+ completeOutstandingRequest ( noop , taskType ) ;
348
399
return true ;
349
400
}
350
401
return false ;
0 commit comments