UNPKG

8.82 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
8
9var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
10
11var _angular = require('angular');
12
13var _angular2 = _interopRequireDefault(_angular);
14
15var _constants = require('./constants');
16
17var _constants2 = _interopRequireDefault(_constants);
18
19var _utils = require('../utils');
20
21function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22
23function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
24
25var AvPollingService = function () {
26 function AvPollingService($rootScope, $q, $injector, $timeout, $log, AV_POLLING, AV_API) {
27 _classCallCheck(this, AvPollingService);
28
29 this.av = { $rootScope: $rootScope, $q: $q, $injector: $injector, $timeout: $timeout, $log: $log, AV_POLLING: AV_POLLING, AV_API: AV_API };
30 this.pendingRequests = []; // stores all request for polling
31 }
32
33 _createClass(AvPollingService, [{
34 key: 'response',
35 value: function response(_response) {
36
37 if (this.isAsyncResponse(_response)) {
38 return this.onAsyncReponse(_response);
39 }
40
41 return _response || this.av.$q.when(_response);
42 }
43 }, {
44 key: 'setDefaults',
45 value: function setDefaults(config) {
46
47 var defaultOptions = {
48 pollingInterval: this.av.AV_POLLING.INTERVAL,
49 pollingDecay: this.av.AV_POLLING.DECAY,
50 pollingMaxInterval: this.av.AV_POLLING.MAX_ELAPSED_TIME,
51 pollingRetryCount: 0,
52 pollingStartTime: new Date().getTime()
53 };
54
55 return _extends(defaultOptions, config);
56 }
57 }, {
58 key: 'responseError',
59 value: function responseError(response) {
60 // Return the promise rejection
61 return this.av.$q.reject(response);
62 }
63
64 /**
65 * API layer return a link with a polling url for
66 * async responses.
67 *
68 * @param {Object} response ajax response
69 * @return {Boolean} true if response has status of 202 (accepted) and location param in header with uri+session link
70 */
71
72 }, {
73 key: 'isAsyncResponse',
74 value: function isAsyncResponse(response) {
75
76 return response && response.config && response.config.api && response.status && response.status === 202 && _angular2.default.isFunction(response.headers) && !(0, _utils.isBlank)(response.headers(this.av.AV_API.HEADERS.SERVER.LOCATION));
77 }
78 }, {
79 key: 'onAsyncReponse',
80 value: function onAsyncReponse(response) {
81
82 response.config = this.setDefaults(response.config);
83
84 var deferred = this.av.$q.defer();
85
86 this.queueRequest(deferred, response);
87
88 // [rm3]: Can't call notify before you return promise object?
89 this.av.$timeout(function () {
90 // Notify deferred listeners with the original server response
91 deferred.notify(response);
92 }, 0, false);
93
94 return deferred.promise;
95 }
96 }, {
97 key: 'getUrl',
98 value: function getUrl(url) {
99
100 var result = url.match(this.av.AV_POLLING.REGEX_URL);
101 if (result && result[1]) {
102 return '/api' + result[1];
103 }
104
105 return url;
106 }
107 }, {
108 key: 'queueRequest',
109 value: function queueRequest(deferred, response) {
110
111 var self = this;
112 // server replies with location header so set the url into config
113 var _url = (0, _utils.getRelativeUrl)(response.headers(this.av.AV_API.HEADERS.SERVER.LOCATION));
114 var _config = response.config;
115
116 // headers – {Object} – Map of strings or functions which return strings representing HTTP headers
117 // to send to the server. If the return value of a function is null, the header
118 // will not be sent. Functions accept a config object as an argument.
119 var config = {
120 method: 'GET',
121 api: true,
122 headers: _config.headers,
123 pollingInterval: _config.pollingInterval,
124 pollingMaxRetry: _config.pollingMaxRetry,
125 pollingMaxInterval: _config.pollingMaxInterval,
126 pollingStartTime: _config.pollingStartTime,
127 _pollingDecay: _config._pollingDecay,
128 pollingRetryCount: _config.pollingRetryCount,
129 pollingDecay: _config.pollingDecay,
130 url: _url, /* set the url from the server response */
131 cache: false
132 };
133
134 var request = {
135 id: (0, _utils.uuid)('request-'),
136 config: config,
137 deferred: deferred
138 };
139
140 var timeout = this.getPollingTimeout(config);
141
142 // each async request should run on its own timer
143 var timer = this.av.$timeout(function () {
144 self.retryRequest(request.id);
145 }, timeout, false);
146
147 request.timer = timer;
148
149 // add the async request to the queue
150 this.pushRequest(request);
151 }
152 }, {
153 key: 'popRequest',
154 value: function popRequest(id) {
155
156 var index = null;
157 var request = null;
158
159 for (var i = 0; i < this.pendingRequests.length; i++) {
160 if (this.pendingRequests[i].id === id) {
161 index = i;
162 break;
163 }
164 }
165
166 request = this.pendingRequests[index];
167 this.pendingRequests.splice(index, 1);
168
169 return request;
170 }
171 }, {
172 key: 'pushRequest',
173 value: function pushRequest(request) {
174 this.pendingRequests.push(request);
175 }
176 }, {
177 key: 'getPollingTimeout',
178 value: function getPollingTimeout(config) {
179 return config.pollingDecay * config.pollingInterval;
180 }
181 }, {
182 key: 'isPollingMaxTimeout',
183 value: function isPollingMaxTimeout(config) {
184 var now = new Date().getTime();
185 var elaspedTime = now - config.pollingStartTime;
186 var isElapsed = elaspedTime > config.pollingMaxInterval;
187 return isElapsed;
188 }
189 }, {
190 key: 'isMaxRetried',
191 value: function isMaxRetried(config) {
192 return config.pollingRetryCount >= this.av.AV_POLLING.MAX_RETRY;
193 }
194 }, {
195 key: 'isPollable',
196 value: function isPollable(config) {
197 var _isTimeout = this.isPollingMaxTimeout(config);
198 var _isMax = this.isMaxRetried(config);
199
200 return _isTimeout || _isMax ? false : true;
201 }
202 }, {
203 key: 'retryRequest',
204 value: function retryRequest(id) {
205
206 var self = this;
207 var request = this.popRequest(id);
208 this.av.$timeout.cancel(request.timer);
209
210 var config = request.config;
211
212 var deferred = request.deferred;
213
214 if (!this.isPollable(config)) {
215 this.av.$log.info('Rejecting pollable response due to timeout');
216 return deferred.reject(request);
217 }
218
219 // increment counters and polling timeouts
220 this.increment(config);
221
222 function successCallback(response) {
223 if (self.isAsyncResponse(response)) {
224 deferred.notify(response);
225 self.queueRequest(request.deferred, response);
226 } else {
227 deferred.resolve(response);
228 }
229 }
230
231 function errorCallback(response) {
232 deferred.reject(response);
233 }
234
235 // Silly circular dependency trick
236 var $http = this.av.$injector.get('$http');
237
238 $http(config).then(successCallback, errorCallback);
239 }
240 }, {
241 key: 'increment',
242 value: function increment(config) {
243 this.incrementCounter(config);
244 this.incrementDecay(config);
245 }
246 }, {
247 key: 'incrementDecay',
248 value: function incrementDecay(config) {
249 if (!config._pollingDecay) {
250 // store the original decay param
251 config._pollingDecay = config.pollingDecay;
252 }
253 config.pollingDecay *= config._pollingDecay;
254 }
255 }, {
256 key: 'incrementCounter',
257 value: function incrementCounter(config) {
258 config.pollingRetryCount++;
259 }
260 }, {
261 key: 'clearRequests',
262 value: function clearRequests() {
263 var self = this;
264 _angular2.default.forEach(this.pendingRequests, function (request) {
265 self.av.$timeout.cancel(request.timer);
266 });
267 this.pendingRequests = [];
268 }
269 }]);
270
271 return AvPollingService;
272}();
273
274_constants2.default.service('avPollingService', AvPollingService);
275
276exports.default = _constants2.default;
\No newline at end of file