1 | import { Observable } from '../../data/observable';
|
2 | export 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 |
|
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 |
|
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 |
|
91 | throw new Error('Abstract');
|
92 | }
|
93 | set(key, image) {
|
94 |
|
95 | throw new Error('Abstract');
|
96 | }
|
97 | remove(key) {
|
98 |
|
99 | throw new Error('Abstract');
|
100 | }
|
101 | clear() {
|
102 |
|
103 | throw new Error('Abstract');
|
104 | }
|
105 |
|
106 | _downloadCore(request) {
|
107 |
|
108 | throw new Error('Abstract');
|
109 | }
|
110 |
|
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 | }
|
174 | Cache.downloadedEvent = 'downloaded';
|
175 | Cache.downloadErrorEvent = 'downloadError';
|
176 |
|
\ | No newline at end of file |