IteratorObservable.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import { root } from '../util/root';
  2. import { Observable } from '../Observable';
  3. import { iterator as Symbol_iterator } from '../symbol/iterator';
  4. /**
  5. * We need this JSDoc comment for affecting ESDoc.
  6. * @extends {Ignored}
  7. * @hide true
  8. */
  9. export class IteratorObservable extends Observable {
  10. constructor(iterator, scheduler) {
  11. super();
  12. this.scheduler = scheduler;
  13. if (iterator == null) {
  14. throw new Error('iterator cannot be null.');
  15. }
  16. this.iterator = getIterator(iterator);
  17. }
  18. static create(iterator, scheduler) {
  19. return new IteratorObservable(iterator, scheduler);
  20. }
  21. static dispatch(state) {
  22. const { index, hasError, iterator, subscriber } = state;
  23. if (hasError) {
  24. subscriber.error(state.error);
  25. return;
  26. }
  27. let result = iterator.next();
  28. if (result.done) {
  29. subscriber.complete();
  30. return;
  31. }
  32. subscriber.next(result.value);
  33. state.index = index + 1;
  34. if (subscriber.closed) {
  35. if (typeof iterator.return === 'function') {
  36. iterator.return();
  37. }
  38. return;
  39. }
  40. this.schedule(state);
  41. }
  42. /** @deprecated internal use only */ _subscribe(subscriber) {
  43. let index = 0;
  44. const { iterator, scheduler } = this;
  45. if (scheduler) {
  46. return scheduler.schedule(IteratorObservable.dispatch, 0, {
  47. index, iterator, subscriber
  48. });
  49. }
  50. else {
  51. do {
  52. let result = iterator.next();
  53. if (result.done) {
  54. subscriber.complete();
  55. break;
  56. }
  57. else {
  58. subscriber.next(result.value);
  59. }
  60. if (subscriber.closed) {
  61. if (typeof iterator.return === 'function') {
  62. iterator.return();
  63. }
  64. break;
  65. }
  66. } while (true);
  67. }
  68. }
  69. }
  70. class StringIterator {
  71. constructor(str, idx = 0, len = str.length) {
  72. this.str = str;
  73. this.idx = idx;
  74. this.len = len;
  75. }
  76. [Symbol_iterator]() { return (this); }
  77. next() {
  78. return this.idx < this.len ? {
  79. done: false,
  80. value: this.str.charAt(this.idx++)
  81. } : {
  82. done: true,
  83. value: undefined
  84. };
  85. }
  86. }
  87. class ArrayIterator {
  88. constructor(arr, idx = 0, len = toLength(arr)) {
  89. this.arr = arr;
  90. this.idx = idx;
  91. this.len = len;
  92. }
  93. [Symbol_iterator]() { return this; }
  94. next() {
  95. return this.idx < this.len ? {
  96. done: false,
  97. value: this.arr[this.idx++]
  98. } : {
  99. done: true,
  100. value: undefined
  101. };
  102. }
  103. }
  104. function getIterator(obj) {
  105. const i = obj[Symbol_iterator];
  106. if (!i && typeof obj === 'string') {
  107. return new StringIterator(obj);
  108. }
  109. if (!i && obj.length !== undefined) {
  110. return new ArrayIterator(obj);
  111. }
  112. if (!i) {
  113. throw new TypeError('object is not iterable');
  114. }
  115. return obj[Symbol_iterator]();
  116. }
  117. const maxSafeInteger = Math.pow(2, 53) - 1;
  118. function toLength(o) {
  119. let len = +o.length;
  120. if (isNaN(len)) {
  121. return 0;
  122. }
  123. if (len === 0 || !numberIsFinite(len)) {
  124. return len;
  125. }
  126. len = sign(len) * Math.floor(Math.abs(len));
  127. if (len <= 0) {
  128. return 0;
  129. }
  130. if (len > maxSafeInteger) {
  131. return maxSafeInteger;
  132. }
  133. return len;
  134. }
  135. function numberIsFinite(value) {
  136. return typeof value === 'number' && root.isFinite(value);
  137. }
  138. function sign(value) {
  139. let valueAsNumber = +value;
  140. if (valueAsNumber === 0) {
  141. return valueAsNumber;
  142. }
  143. if (isNaN(valueAsNumber)) {
  144. return valueAsNumber;
  145. }
  146. return valueAsNumber < 0 ? -1 : 1;
  147. }
  148. //# sourceMappingURL=IteratorObservable.js.map