Observable.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.Observable = void 0;
  6. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  7. 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); } }
  8. function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  9. // === Symbol Support ===
  10. var hasSymbols = function () {
  11. return typeof Symbol === 'function';
  12. };
  13. var hasSymbol = function (name) {
  14. return hasSymbols() && Boolean(Symbol[name]);
  15. };
  16. var getSymbol = function (name) {
  17. return hasSymbol(name) ? Symbol[name] : '@@' + name;
  18. };
  19. if (hasSymbols() && !hasSymbol('observable')) {
  20. Symbol.observable = Symbol('observable');
  21. }
  22. var SymbolIterator = getSymbol('iterator');
  23. var SymbolObservable = getSymbol('observable');
  24. var SymbolSpecies = getSymbol('species'); // === Abstract Operations ===
  25. function getMethod(obj, key) {
  26. var value = obj[key];
  27. if (value == null) return undefined;
  28. if (typeof value !== 'function') throw new TypeError(value + ' is not a function');
  29. return value;
  30. }
  31. function getSpecies(obj) {
  32. var ctor = obj.constructor;
  33. if (ctor !== undefined) {
  34. ctor = ctor[SymbolSpecies];
  35. if (ctor === null) {
  36. ctor = undefined;
  37. }
  38. }
  39. return ctor !== undefined ? ctor : Observable;
  40. }
  41. function isObservable(x) {
  42. return x instanceof Observable; // SPEC: Brand check
  43. }
  44. function hostReportError(e) {
  45. if (hostReportError.log) {
  46. hostReportError.log(e);
  47. } else {
  48. setTimeout(function () {
  49. throw e;
  50. });
  51. }
  52. }
  53. function enqueue(fn) {
  54. Promise.resolve().then(function () {
  55. try {
  56. fn();
  57. } catch (e) {
  58. hostReportError(e);
  59. }
  60. });
  61. }
  62. function cleanupSubscription(subscription) {
  63. var cleanup = subscription._cleanup;
  64. if (cleanup === undefined) return;
  65. subscription._cleanup = undefined;
  66. if (!cleanup) {
  67. return;
  68. }
  69. try {
  70. if (typeof cleanup === 'function') {
  71. cleanup();
  72. } else {
  73. var unsubscribe = getMethod(cleanup, 'unsubscribe');
  74. if (unsubscribe) {
  75. unsubscribe.call(cleanup);
  76. }
  77. }
  78. } catch (e) {
  79. hostReportError(e);
  80. }
  81. }
  82. function closeSubscription(subscription) {
  83. subscription._observer = undefined;
  84. subscription._queue = undefined;
  85. subscription._state = 'closed';
  86. }
  87. function flushSubscription(subscription) {
  88. var queue = subscription._queue;
  89. if (!queue) {
  90. return;
  91. }
  92. subscription._queue = undefined;
  93. subscription._state = 'ready';
  94. for (var i = 0; i < queue.length; ++i) {
  95. notifySubscription(subscription, queue[i].type, queue[i].value);
  96. if (subscription._state === 'closed') break;
  97. }
  98. }
  99. function notifySubscription(subscription, type, value) {
  100. subscription._state = 'running';
  101. var observer = subscription._observer;
  102. try {
  103. var m = getMethod(observer, type);
  104. switch (type) {
  105. case 'next':
  106. if (m) m.call(observer, value);
  107. break;
  108. case 'error':
  109. closeSubscription(subscription);
  110. if (m) m.call(observer, value);else throw value;
  111. break;
  112. case 'complete':
  113. closeSubscription(subscription);
  114. if (m) m.call(observer);
  115. break;
  116. }
  117. } catch (e) {
  118. hostReportError(e);
  119. }
  120. if (subscription._state === 'closed') cleanupSubscription(subscription);else if (subscription._state === 'running') subscription._state = 'ready';
  121. }
  122. function onNotify(subscription, type, value) {
  123. if (subscription._state === 'closed') return;
  124. if (subscription._state === 'buffering') {
  125. subscription._queue.push({
  126. type: type,
  127. value: value
  128. });
  129. return;
  130. }
  131. if (subscription._state !== 'ready') {
  132. subscription._state = 'buffering';
  133. subscription._queue = [{
  134. type: type,
  135. value: value
  136. }];
  137. enqueue(function () {
  138. return flushSubscription(subscription);
  139. });
  140. return;
  141. }
  142. notifySubscription(subscription, type, value);
  143. }
  144. var Subscription =
  145. /*#__PURE__*/
  146. function () {
  147. function Subscription(observer, subscriber) {
  148. _classCallCheck(this, Subscription);
  149. // ASSERT: observer is an object
  150. // ASSERT: subscriber is callable
  151. this._cleanup = undefined;
  152. this._observer = observer;
  153. this._queue = undefined;
  154. this._state = 'initializing';
  155. var subscriptionObserver = new SubscriptionObserver(this);
  156. try {
  157. this._cleanup = subscriber.call(undefined, subscriptionObserver);
  158. } catch (e) {
  159. subscriptionObserver.error(e);
  160. }
  161. if (this._state === 'initializing') this._state = 'ready';
  162. }
  163. _createClass(Subscription, [{
  164. key: "unsubscribe",
  165. value: function unsubscribe() {
  166. if (this._state !== 'closed') {
  167. closeSubscription(this);
  168. cleanupSubscription(this);
  169. }
  170. }
  171. }, {
  172. key: "closed",
  173. get: function () {
  174. return this._state === 'closed';
  175. }
  176. }]);
  177. return Subscription;
  178. }();
  179. var SubscriptionObserver =
  180. /*#__PURE__*/
  181. function () {
  182. function SubscriptionObserver(subscription) {
  183. _classCallCheck(this, SubscriptionObserver);
  184. this._subscription = subscription;
  185. }
  186. _createClass(SubscriptionObserver, [{
  187. key: "next",
  188. value: function next(value) {
  189. onNotify(this._subscription, 'next', value);
  190. }
  191. }, {
  192. key: "error",
  193. value: function error(value) {
  194. onNotify(this._subscription, 'error', value);
  195. }
  196. }, {
  197. key: "complete",
  198. value: function complete() {
  199. onNotify(this._subscription, 'complete');
  200. }
  201. }, {
  202. key: "closed",
  203. get: function () {
  204. return this._subscription._state === 'closed';
  205. }
  206. }]);
  207. return SubscriptionObserver;
  208. }();
  209. var Observable =
  210. /*#__PURE__*/
  211. function () {
  212. function Observable(subscriber) {
  213. _classCallCheck(this, Observable);
  214. if (!(this instanceof Observable)) throw new TypeError('Observable cannot be called as a function');
  215. if (typeof subscriber !== 'function') throw new TypeError('Observable initializer must be a function');
  216. this._subscriber = subscriber;
  217. }
  218. _createClass(Observable, [{
  219. key: "subscribe",
  220. value: function subscribe(observer) {
  221. if (typeof observer !== 'object' || observer === null) {
  222. observer = {
  223. next: observer,
  224. error: arguments[1],
  225. complete: arguments[2]
  226. };
  227. }
  228. return new Subscription(observer, this._subscriber);
  229. }
  230. }, {
  231. key: "forEach",
  232. value: function forEach(fn) {
  233. var _this = this;
  234. return new Promise(function (resolve, reject) {
  235. if (typeof fn !== 'function') {
  236. reject(new TypeError(fn + ' is not a function'));
  237. return;
  238. }
  239. function done() {
  240. subscription.unsubscribe();
  241. resolve();
  242. }
  243. var subscription = _this.subscribe({
  244. next: function (value) {
  245. try {
  246. fn(value, done);
  247. } catch (e) {
  248. reject(e);
  249. subscription.unsubscribe();
  250. }
  251. },
  252. error: reject,
  253. complete: resolve
  254. });
  255. });
  256. }
  257. }, {
  258. key: "map",
  259. value: function map(fn) {
  260. var _this2 = this;
  261. if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
  262. var C = getSpecies(this);
  263. return new C(function (observer) {
  264. return _this2.subscribe({
  265. next: function (value) {
  266. try {
  267. value = fn(value);
  268. } catch (e) {
  269. return observer.error(e);
  270. }
  271. observer.next(value);
  272. },
  273. error: function (e) {
  274. observer.error(e);
  275. },
  276. complete: function () {
  277. observer.complete();
  278. }
  279. });
  280. });
  281. }
  282. }, {
  283. key: "filter",
  284. value: function filter(fn) {
  285. var _this3 = this;
  286. if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
  287. var C = getSpecies(this);
  288. return new C(function (observer) {
  289. return _this3.subscribe({
  290. next: function (value) {
  291. try {
  292. if (!fn(value)) return;
  293. } catch (e) {
  294. return observer.error(e);
  295. }
  296. observer.next(value);
  297. },
  298. error: function (e) {
  299. observer.error(e);
  300. },
  301. complete: function () {
  302. observer.complete();
  303. }
  304. });
  305. });
  306. }
  307. }, {
  308. key: "reduce",
  309. value: function reduce(fn) {
  310. var _this4 = this;
  311. if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
  312. var C = getSpecies(this);
  313. var hasSeed = arguments.length > 1;
  314. var hasValue = false;
  315. var seed = arguments[1];
  316. var acc = seed;
  317. return new C(function (observer) {
  318. return _this4.subscribe({
  319. next: function (value) {
  320. var first = !hasValue;
  321. hasValue = true;
  322. if (!first || hasSeed) {
  323. try {
  324. acc = fn(acc, value);
  325. } catch (e) {
  326. return observer.error(e);
  327. }
  328. } else {
  329. acc = value;
  330. }
  331. },
  332. error: function (e) {
  333. observer.error(e);
  334. },
  335. complete: function () {
  336. if (!hasValue && !hasSeed) return observer.error(new TypeError('Cannot reduce an empty sequence'));
  337. observer.next(acc);
  338. observer.complete();
  339. }
  340. });
  341. });
  342. }
  343. }, {
  344. key: "concat",
  345. value: function concat() {
  346. var _this5 = this;
  347. for (var _len = arguments.length, sources = new Array(_len), _key = 0; _key < _len; _key++) {
  348. sources[_key] = arguments[_key];
  349. }
  350. var C = getSpecies(this);
  351. return new C(function (observer) {
  352. var subscription;
  353. var index = 0;
  354. function startNext(next) {
  355. subscription = next.subscribe({
  356. next: function (v) {
  357. observer.next(v);
  358. },
  359. error: function (e) {
  360. observer.error(e);
  361. },
  362. complete: function () {
  363. if (index === sources.length) {
  364. subscription = undefined;
  365. observer.complete();
  366. } else {
  367. startNext(C.from(sources[index++]));
  368. }
  369. }
  370. });
  371. }
  372. startNext(_this5);
  373. return function () {
  374. if (subscription) {
  375. subscription.unsubscribe();
  376. subscription = undefined;
  377. }
  378. };
  379. });
  380. }
  381. }, {
  382. key: "flatMap",
  383. value: function flatMap(fn) {
  384. var _this6 = this;
  385. if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
  386. var C = getSpecies(this);
  387. return new C(function (observer) {
  388. var subscriptions = [];
  389. var outer = _this6.subscribe({
  390. next: function (value) {
  391. if (fn) {
  392. try {
  393. value = fn(value);
  394. } catch (e) {
  395. return observer.error(e);
  396. }
  397. }
  398. var inner = C.from(value).subscribe({
  399. next: function (value) {
  400. observer.next(value);
  401. },
  402. error: function (e) {
  403. observer.error(e);
  404. },
  405. complete: function () {
  406. var i = subscriptions.indexOf(inner);
  407. if (i >= 0) subscriptions.splice(i, 1);
  408. completeIfDone();
  409. }
  410. });
  411. subscriptions.push(inner);
  412. },
  413. error: function (e) {
  414. observer.error(e);
  415. },
  416. complete: function () {
  417. completeIfDone();
  418. }
  419. });
  420. function completeIfDone() {
  421. if (outer.closed && subscriptions.length === 0) observer.complete();
  422. }
  423. return function () {
  424. subscriptions.forEach(function (s) {
  425. return s.unsubscribe();
  426. });
  427. outer.unsubscribe();
  428. };
  429. });
  430. }
  431. }, {
  432. key: SymbolObservable,
  433. value: function () {
  434. return this;
  435. }
  436. }], [{
  437. key: "from",
  438. value: function from(x) {
  439. var C = typeof this === 'function' ? this : Observable;
  440. if (x == null) throw new TypeError(x + ' is not an object');
  441. var method = getMethod(x, SymbolObservable);
  442. if (method) {
  443. var observable = method.call(x);
  444. if (Object(observable) !== observable) throw new TypeError(observable + ' is not an object');
  445. if (isObservable(observable) && observable.constructor === C) return observable;
  446. return new C(function (observer) {
  447. return observable.subscribe(observer);
  448. });
  449. }
  450. if (hasSymbol('iterator')) {
  451. method = getMethod(x, SymbolIterator);
  452. if (method) {
  453. return new C(function (observer) {
  454. enqueue(function () {
  455. if (observer.closed) return;
  456. var _iteratorNormalCompletion = true;
  457. var _didIteratorError = false;
  458. var _iteratorError = undefined;
  459. try {
  460. for (var _iterator = method.call(x)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
  461. var _item = _step.value;
  462. observer.next(_item);
  463. if (observer.closed) return;
  464. }
  465. } catch (err) {
  466. _didIteratorError = true;
  467. _iteratorError = err;
  468. } finally {
  469. try {
  470. if (!_iteratorNormalCompletion && _iterator.return != null) {
  471. _iterator.return();
  472. }
  473. } finally {
  474. if (_didIteratorError) {
  475. throw _iteratorError;
  476. }
  477. }
  478. }
  479. observer.complete();
  480. });
  481. });
  482. }
  483. }
  484. if (Array.isArray(x)) {
  485. return new C(function (observer) {
  486. enqueue(function () {
  487. if (observer.closed) return;
  488. for (var i = 0; i < x.length; ++i) {
  489. observer.next(x[i]);
  490. if (observer.closed) return;
  491. }
  492. observer.complete();
  493. });
  494. });
  495. }
  496. throw new TypeError(x + ' is not observable');
  497. }
  498. }, {
  499. key: "of",
  500. value: function of() {
  501. for (var _len2 = arguments.length, items = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  502. items[_key2] = arguments[_key2];
  503. }
  504. var C = typeof this === 'function' ? this : Observable;
  505. return new C(function (observer) {
  506. enqueue(function () {
  507. if (observer.closed) return;
  508. for (var i = 0; i < items.length; ++i) {
  509. observer.next(items[i]);
  510. if (observer.closed) return;
  511. }
  512. observer.complete();
  513. });
  514. });
  515. }
  516. }, {
  517. key: SymbolSpecies,
  518. get: function () {
  519. return this;
  520. }
  521. }]);
  522. return Observable;
  523. }();
  524. exports.Observable = Observable;
  525. if (hasSymbols()) {
  526. Object.defineProperty(Observable, Symbol('extensions'), {
  527. value: {
  528. symbol: SymbolObservable,
  529. hostReportError: hostReportError
  530. },
  531. configurable: true
  532. });
  533. }