UNPKG

5.85 kBJavaScriptView Raw
1import { Observable } from '../../data/observable';
2export class Cache extends Observable {
3 constructor() {
4 super(...arguments);
5 this.maxRequests = 5;
6 this._enabled = true;
7 this._pendingDownloads = {};
8 this._queue = [];
9 this._currentDownloads = 0;
10 }
11 enableDownload() {
12 if (this._enabled) {
13 return;
14 }
15 // schedule all pending downloads
16 this._enabled = true;
17 let request;
18 while (this._queue.length > 0 && this._currentDownloads < this.maxRequests) {
19 request = this._queue.pop();
20 if (!(request.key in this._pendingDownloads)) {
21 this._download(request);
22 }
23 }
24 }
25 disableDownload() {
26 if (!this._enabled) {
27 return;
28 }
29 this._enabled = false;
30 }
31 push(request) {
32 this._addRequest(request, true);
33 }
34 enqueue(request) {
35 this._addRequest(request, false);
36 }
37 _addRequest(request, onTop) {
38 if (request.key in this._pendingDownloads) {
39 const existingRequest = this._pendingDownloads[request.key];
40 this._mergeRequests(existingRequest, request);
41 }
42 else {
43 // TODO: Potential performance bottleneck - traversing the whole queue on each download request.
44 let queueRequest;
45 for (let i = 0; i < this._queue.length; i++) {
46 if (this._queue[i].key === request.key) {
47 queueRequest = this._queue[i];
48 break;
49 }
50 }
51 if (queueRequest) {
52 this._mergeRequests(queueRequest, request);
53 }
54 else {
55 if (this._shouldDownload(request, onTop)) {
56 this._download(request);
57 }
58 }
59 }
60 }
61 _mergeRequests(existingRequest, newRequest) {
62 if (existingRequest.completed) {
63 if (newRequest.completed) {
64 const existingCompleted = existingRequest.completed;
65 const stackCompleted = function (result, key) {
66 existingCompleted(result, key);
67 newRequest.completed(result, key);
68 };
69 existingRequest.completed = stackCompleted;
70 }
71 }
72 else {
73 existingRequest.completed = newRequest.completed;
74 }
75 if (existingRequest.error) {
76 if (newRequest.error) {
77 const existingError = existingRequest.error;
78 const stackError = function (key) {
79 existingError(key);
80 newRequest.error(key);
81 };
82 existingRequest.error = stackError;
83 }
84 }
85 else {
86 existingRequest.error = newRequest.error;
87 }
88 }
89 get(key) {
90 // This method is intended to be overridden by the android and ios implementations
91 throw new Error('Abstract');
92 }
93 set(key, image) {
94 // This method is intended to be overridden by the android and ios implementations
95 throw new Error('Abstract');
96 }
97 remove(key) {
98 // This method is intended to be overridden by the android and ios implementations
99 throw new Error('Abstract');
100 }
101 clear() {
102 // This method is intended to be overridden by the android and ios implementations
103 throw new Error('Abstract');
104 }
105 /* tslint:disable:no-unused-variable */
106 _downloadCore(request) {
107 // This method is intended to be overridden by the android and ios implementations
108 throw new Error('Abstract');
109 }
110 /* tslint:enable:no-unused-variable */
111 _onDownloadCompleted(key, image) {
112 const request = this._pendingDownloads[key];
113 this.set(request.key, image);
114 this._currentDownloads--;
115 if (request.completed) {
116 request.completed(image, request.key);
117 }
118 if (this.hasListeners(Cache.downloadedEvent)) {
119 this.notify({
120 eventName: Cache.downloadedEvent,
121 object: this,
122 key: key,
123 image: image,
124 });
125 }
126 delete this._pendingDownloads[request.key];
127 this._updateQueue();
128 }
129 _onDownloadError(key, err) {
130 const request = this._pendingDownloads[key];
131 this._currentDownloads--;
132 if (request.error) {
133 request.error(request.key);
134 }
135 if (this.hasListeners(Cache.downloadErrorEvent)) {
136 this.notify({
137 eventName: Cache.downloadErrorEvent,
138 object: this,
139 key: key,
140 error: err,
141 });
142 }
143 delete this._pendingDownloads[request.key];
144 this._updateQueue();
145 }
146 _shouldDownload(request, onTop) {
147 if (this.get(request.key) || request.key in this._pendingDownloads) {
148 return false;
149 }
150 if (this._currentDownloads >= this.maxRequests || !this._enabled) {
151 if (onTop) {
152 this._queue.push(request);
153 }
154 else {
155 this._queue.unshift(request);
156 }
157 return false;
158 }
159 return true;
160 }
161 _download(request) {
162 this._currentDownloads++;
163 this._pendingDownloads[request.key] = request;
164 this._downloadCore(request);
165 }
166 _updateQueue() {
167 if (!this._enabled || this._queue.length === 0 || this._currentDownloads === this.maxRequests) {
168 return;
169 }
170 const request = this._queue.pop();
171 this._download(request);
172 }
173}
174Cache.downloadedEvent = 'downloaded';
175Cache.downloadErrorEvent = 'downloadError';
176//# sourceMappingURL=image-cache-common.js.map
\No newline at end of file