PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs/rxjs/2.1.1/rx.joinpatterns.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 403 lines | 256 code | 39 blank | 108 comment | 42 complexity | 943e1127de6dc22a4ce26cd7069dbb9f MD5 | raw file
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. (function (root, factory) {
  3. var freeExports = typeof exports == 'object' && exports &&
  4. (typeof root == 'object' && root && root == root.global && (window = root), exports);
  5. // Because of build optimizers
  6. if (typeof define === 'function' && define.amd) {
  7. define(['rx', 'exports'], function (Rx, exports) {
  8. root.Rx = factory(root, exports, Rx);
  9. return root.Rx;
  10. });
  11. } else if (typeof module == 'object' && module && module.exports == freeExports) {
  12. module.exports = factory(root, module.exports, require('./rx'));
  13. } else {
  14. root.Rx = factory(root, {}, root.Rx);
  15. }
  16. }(this, function (global, exp, Rx, undefined) {
  17. // Aliases
  18. var Observable = Rx.Observable,
  19. observableProto = Observable.prototype,
  20. AnonymousObservable = Rx.Internals.AnonymousObservable,
  21. observableThrow = Observable.throwException,
  22. observerCreate = Rx.Observer.create,
  23. SingleAssignmentDisposable = Rx.SingleAssignmentDisposable,
  24. CompositeDisposable = Rx.CompositeDisposable,
  25. AbstractObserver = Rx.Internals.AbstractObserver;
  26. // Defaults
  27. function defaultComparer(x, y) { return x === y; }
  28. function noop() { }
  29. // Utilities
  30. var inherits = Rx.Internals.inherits;
  31. var slice = Array.prototype.slice;
  32. function argsOrArray(args, idx) {
  33. return args.length === 1 && Array.isArray(args[idx]) ?
  34. args[idx] :
  35. slice.call(args);
  36. }
  37. /** @private */
  38. var Map = (function () {
  39. /**
  40. * @constructor
  41. * @private
  42. */
  43. function Map() {
  44. this.keys = [];
  45. this.values = [];
  46. }
  47. /**
  48. * @private
  49. * @memberOf Map#
  50. */
  51. Map.prototype['delete'] = function (key) {
  52. var i = this.keys.indexOf(key);
  53. if (i !== -1) {
  54. this.keys.splice(i, 1);
  55. this.values.splice(i, 1);
  56. }
  57. return i !== -1;
  58. };
  59. /**
  60. * @private
  61. * @memberOf Map#
  62. */
  63. Map.prototype.get = function (key, fallback) {
  64. var i = this.keys.indexOf(key);
  65. return i !== -1 ? this.values[i] : fallback;
  66. };
  67. /**
  68. * @private
  69. * @memberOf Map#
  70. */
  71. Map.prototype.set = function (key, value) {
  72. var i = this.keys.indexOf(key);
  73. if (i !== -1) {
  74. this.values[i] = value;
  75. }
  76. this.values[this.keys.push(key) - 1] = value;
  77. };
  78. /**
  79. * @private
  80. * @memberOf Map#
  81. */
  82. Map.prototype.size = function () { return this.keys.length; };
  83. /**
  84. * @private
  85. * @memberOf Map#
  86. */
  87. Map.prototype.has = function (key) {
  88. return this.keys.indexOf(key) !== -1;
  89. };
  90. /**
  91. * @private
  92. * @memberOf Map#
  93. */
  94. Map.prototype.getKeys = function () { return this.keys.slice(0); };
  95. /**
  96. * @private
  97. * @memberOf Map#
  98. */
  99. Map.prototype.getValues = function () { return this.values.slice(0); };
  100. return Map;
  101. }());
  102. /**
  103. * @constructor
  104. * Represents a join pattern over observable sequences.
  105. */
  106. function Pattern(patterns) {
  107. this.patterns = patterns;
  108. }
  109. /**
  110. * Creates a pattern that matches the current plan matches and when the specified observable sequences has an available value.
  111. *
  112. * @param other Observable sequence to match in addition to the current pattern.
  113. * @return Pattern object that matches when all observable sequences in the pattern have an available value.
  114. */
  115. Pattern.prototype.and = function (other) {
  116. var patterns = this.patterns.slice(0);
  117. patterns.push(other);
  118. return new Pattern(patterns);
  119. };
  120. /**
  121. * Matches when all observable sequences in the pattern (specified using a chain of and operators) have an available value and projects the values.
  122. *
  123. * @param selector Selector that will be invoked with available values from the source sequences, in the same order of the sequences in the pattern.
  124. * @return Plan that produces the projected values, to be fed (with other plans) to the when operator.
  125. */
  126. Pattern.prototype.then = function (selector) {
  127. return new Plan(this, selector);
  128. };
  129. // Plan
  130. function Plan(expression, selector) {
  131. this.expression = expression;
  132. this.selector = selector;
  133. }
  134. Plan.prototype.activate = function (externalSubscriptions, observer, deactivate) {
  135. var self = this;
  136. var joinObservers = [];
  137. for (var i = 0, len = this.expression.patterns.length; i < len; i++) {
  138. joinObservers.push(planCreateObserver(externalSubscriptions, this.expression.patterns[i], observer.onError.bind(observer)));
  139. }
  140. var activePlan = new ActivePlan(joinObservers, function () {
  141. var result;
  142. try {
  143. result = self.selector.apply(self, arguments);
  144. } catch (exception) {
  145. observer.onError(exception);
  146. return;
  147. }
  148. observer.onNext(result);
  149. }, function () {
  150. for (var j = 0, jlen = joinObservers.length; j < jlen; j++) {
  151. joinObservers[j].removeActivePlan(activePlan);
  152. }
  153. deactivate(activePlan);
  154. });
  155. for (i = 0, len = joinObservers.length; i < len; i++) {
  156. joinObservers[i].addActivePlan(activePlan);
  157. }
  158. return activePlan;
  159. };
  160. function planCreateObserver(externalSubscriptions, observable, onError) {
  161. var entry = externalSubscriptions.get(observable);
  162. if (!entry) {
  163. var observer = new JoinObserver(observable, onError);
  164. externalSubscriptions.set(observable, observer);
  165. return observer;
  166. }
  167. return entry;
  168. }
  169. // Active Plan
  170. function ActivePlan(joinObserverArray, onNext, onCompleted) {
  171. var i, joinObserver;
  172. this.joinObserverArray = joinObserverArray;
  173. this.onNext = onNext;
  174. this.onCompleted = onCompleted;
  175. this.joinObservers = new Map();
  176. for (i = 0; i < this.joinObserverArray.length; i++) {
  177. joinObserver = this.joinObserverArray[i];
  178. this.joinObservers.set(joinObserver, joinObserver);
  179. }
  180. }
  181. ActivePlan.prototype.dequeue = function () {
  182. var values = this.joinObservers.getValues();
  183. for (var i = 0, len = values.length; i < len; i++) {
  184. values[i].queue.shift();
  185. }
  186. };
  187. ActivePlan.prototype.match = function () {
  188. var firstValues, i, len, isCompleted, values, hasValues = true;
  189. for (i = 0, len = this.joinObserverArray.length; i < len; i++) {
  190. if (this.joinObserverArray[i].queue.length === 0) {
  191. hasValues = false;
  192. break;
  193. }
  194. }
  195. if (hasValues) {
  196. firstValues = [];
  197. isCompleted = false;
  198. for (i = 0, len = this.joinObserverArray.length; i < len; i++) {
  199. firstValues.push(this.joinObserverArray[i].queue[0]);
  200. if (this.joinObserverArray[i].queue[0].kind === 'C') {
  201. isCompleted = true;
  202. }
  203. }
  204. if (isCompleted) {
  205. this.onCompleted();
  206. } else {
  207. this.dequeue();
  208. values = [];
  209. for (i = 0; i < firstValues.length; i++) {
  210. values.push(firstValues[i].value);
  211. }
  212. this.onNext.apply(this, values);
  213. }
  214. }
  215. };
  216. /** @private */
  217. var JoinObserver = (function (_super) {
  218. inherits(JoinObserver, _super);
  219. /**
  220. * @constructor
  221. * @private
  222. */
  223. function JoinObserver(source, onError) {
  224. _super.call(this);
  225. this.source = source;
  226. this.onError = onError;
  227. this.queue = [];
  228. this.activePlans = [];
  229. this.subscription = new SingleAssignmentDisposable();
  230. this.isDisposed = false;
  231. }
  232. var JoinObserverPrototype = JoinObserver.prototype;
  233. /**
  234. * @memberOf JoinObserver#
  235. * @private
  236. */
  237. JoinObserverPrototype.next = function (notification) {
  238. if (!this.isDisposed) {
  239. if (notification.kind === 'E') {
  240. this.onError(notification.exception);
  241. return;
  242. }
  243. this.queue.push(notification);
  244. var activePlans = this.activePlans.slice(0);
  245. for (var i = 0, len = activePlans.length; i < len; i++) {
  246. activePlans[i].match();
  247. }
  248. }
  249. };
  250. /**
  251. * @memberOf JoinObserver#
  252. * @private
  253. */
  254. JoinObserverPrototype.error = noop;
  255. /**
  256. * @memberOf JoinObserver#
  257. * @private
  258. */
  259. JoinObserverPrototype.completed = noop;
  260. /**
  261. * @memberOf JoinObserver#
  262. * @private
  263. */
  264. JoinObserverPrototype.addActivePlan = function (activePlan) {
  265. this.activePlans.push(activePlan);
  266. };
  267. /**
  268. * @memberOf JoinObserver#
  269. * @private
  270. */
  271. JoinObserverPrototype.subscribe = function () {
  272. this.subscription.disposable(this.source.materialize().subscribe(this));
  273. };
  274. /**
  275. * @memberOf JoinObserver#
  276. * @private
  277. */
  278. JoinObserverPrototype.removeActivePlan = function (activePlan) {
  279. var idx = this.activePlans.indexOf(activePlan);
  280. this.activePlans.splice(idx, 1);
  281. if (this.activePlans.length === 0) {
  282. this.dispose();
  283. }
  284. };
  285. /**
  286. * @memberOf JoinObserver#
  287. * @private
  288. */
  289. JoinObserverPrototype.dispose = function () {
  290. _super.prototype.dispose.call(this);
  291. if (!this.isDisposed) {
  292. this.isDisposed = true;
  293. this.subscription.dispose();
  294. }
  295. };
  296. return JoinObserver;
  297. } (AbstractObserver));
  298. // Observable extensions
  299. /**
  300. * Creates a pattern that matches when both observable sequences have an available value.
  301. *
  302. * @param right Observable sequence to match with the current sequence.</param>
  303. * @return {Pattern} Pattern object that matches when both observable sequences have an available value.
  304. */
  305. observableProto.and = function (right) {
  306. return new Pattern([this, right]);
  307. };
  308. /**
  309. * Matches when the observable sequence has an available value and projects the value.
  310. *
  311. * @param selector Selector that will be invoked for values in the source sequence.</param>
  312. * @returns {Plan} Plan that produces the projected values, to be fed (with other plans) to the when operator.
  313. */
  314. observableProto.then = function (selector) {
  315. return new Pattern([this]).then(selector);
  316. };
  317. /**
  318. * Joins together the results from several patterns.
  319. *
  320. * @param plans A series of plans (specified as an Array of as a series of arguments) created by use of the Then operator on patterns.</param>
  321. * @returns {Observable} Observable sequence with the results form matching several patterns.
  322. */
  323. Observable.when = function () {
  324. var plans = argsOrArray(arguments, 0);
  325. return new AnonymousObservable(function (observer) {
  326. var activePlans = [],
  327. externalSubscriptions = new Map(),
  328. group,
  329. i, len,
  330. joinObserver,
  331. joinValues,
  332. outObserver;
  333. outObserver = observerCreate(observer.onNext.bind(observer), function (exception) {
  334. var values = externalSubscriptions.getValues();
  335. for (var j = 0, jlen = values.length; j < jlen; j++) {
  336. values[j].onError(exception);
  337. }
  338. observer.onError(exception);
  339. }, observer.onCompleted.bind(observer));
  340. try {
  341. for (i = 0, len = plans.length; i < len; i++) {
  342. activePlans.push(plans[i].activate(externalSubscriptions, outObserver, function (activePlan) {
  343. var idx = activePlans.indexOf(activePlan);
  344. activePlans.splice(idx, 1);
  345. if (activePlans.length === 0) {
  346. outObserver.onCompleted();
  347. }
  348. }));
  349. }
  350. } catch (e) {
  351. observableThrow(e).subscribe(observer);
  352. }
  353. group = new CompositeDisposable();
  354. joinValues = externalSubscriptions.getValues();
  355. for (i = 0, len = joinValues.length; i < len; i++) {
  356. joinObserver = joinValues[i];
  357. joinObserver.subscribe();
  358. group.add(joinObserver);
  359. }
  360. return group;
  361. });
  362. };
  363. return Rx;
  364. }));