-
Notifications
You must be signed in to change notification settings - Fork 321
Expand file tree
/
Copy pathwatcher.js
More file actions
136 lines (122 loc) · 3.42 KB
/
watcher.js
File metadata and controls
136 lines (122 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
* @ngdoc provider
* @name filterWatcher
* @kind function
*
* @description
* store specific filters result in $$cache, based on scope life time(avoid memory leak).
* on scope.$destroy remove it's cache from $$cache container
*/
angular.module('a8m.filter-watcher', [])
.provider('filterWatcher', function() {
this.$get = ['$window', '$rootScope', function($window, $rootScope) {
/**
* Cache storing
* @type {Object}
*/
var $$cache = {};
/**
* Scope listeners container
* scope.$destroy => remove all cache keys
* bind to current scope.
* @type {Object}
*/
var $$listeners = {};
/**
* $timeout without triggering the digest cycle
* @type {function}
*/
var $$timeout = $window.setTimeout;
/**
* @description
* get `HashKey` string based on the given arguments.
* @param fName
* @param args Browser argument object
* @returns {string}
*/
function getHashKey(fName, args) {
return [fName, angular.toJson(Array.prototype.slice.call(args))]
.join('#')
.replace(/"/g,'');
}
/**
* @description
* fir on $scope.$destroy,
* remove cache based scope from `$$cache`,
* and remove itself from `$$listeners`
* @param event
*/
function removeCache(event) {
var id = event.targetScope.$id;
forEach($$listeners[id], function(key) {
delete $$cache[key];
});
delete $$listeners[id];
}
/**
* @description
* for angular version that greater than v.1.3.0
* it clear cache when the digest cycle is end.
*/
function cleanStateless() {
$$timeout(function() {
if(!$rootScope.$$phase)
$$cache = {};
});
}
/**
* @description
* Store hashKeys in $$listeners container
* on scope.$destroy, remove them all(bind an event).
* @param scope
* @param hashKey
* @returns {*}
*/
function addListener(scope, hashKey) {
var id = scope.$id;
if(isUndefined($$listeners[id])) {
scope.$on('$destroy', removeCache);
$$listeners[id] = [];
}
return $$listeners[id].push(hashKey);
}
/**
* @description
* return the `cacheKey` or undefined.
* @param filterName
* @param args
* @returns {*}
*/
function $$isMemoized(filterName, args) {
var hashKey = getHashKey(filterName, args);
return $$cache[hashKey];
}
/**
* @description
* store `result` in `$$cache` container, based on the hashKey.
* add $destroy listener and return result
* @param filterName
* @param args
* @param scope
* @param result
* @returns {*}
*/
function $$memoize(filterName, args, scope, result) {
var hashKey = getHashKey(filterName, args);
//store result in `$$cache` container
$$cache[hashKey] = result;
// for angular versions that less than 1.3
// add to `$destroy` listener, a cleaner callback
if(isScope(scope)) {
addListener(scope, hashKey);
} else {
cleanStateless();
}
return result;
}
return {
isMemoized: $$isMemoized,
memoize: $$memoize
}
}];
});