elementAt.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { Subscriber } from '../Subscriber';
  2. import { ArgumentOutOfRangeError } from '../util/ArgumentOutOfRangeError';
  3. /**
  4. * Emits the single value at the specified `index` in a sequence of emissions
  5. * from the source Observable.
  6. *
  7. * <span class="informal">Emits only the i-th value, then completes.</span>
  8. *
  9. * <img src="./img/elementAt.png" width="100%">
  10. *
  11. * `elementAt` returns an Observable that emits the item at the specified
  12. * `index` in the source Observable, or a default value if that `index` is out
  13. * of range and the `default` argument is provided. If the `default` argument is
  14. * not given and the `index` is out of range, the output Observable will emit an
  15. * `ArgumentOutOfRangeError` error.
  16. *
  17. * @example <caption>Emit only the third click event</caption>
  18. * var clicks = Rx.Observable.fromEvent(document, 'click');
  19. * var result = clicks.elementAt(2);
  20. * result.subscribe(x => console.log(x));
  21. *
  22. * // Results in:
  23. * // click 1 = nothing
  24. * // click 2 = nothing
  25. * // click 3 = MouseEvent object logged to console
  26. *
  27. * @see {@link first}
  28. * @see {@link last}
  29. * @see {@link skip}
  30. * @see {@link single}
  31. * @see {@link take}
  32. *
  33. * @throws {ArgumentOutOfRangeError} When using `elementAt(i)`, it delivers an
  34. * ArgumentOutOrRangeError to the Observer's `error` callback if `i < 0` or the
  35. * Observable has completed before emitting the i-th `next` notification.
  36. *
  37. * @param {number} index Is the number `i` for the i-th source emission that has
  38. * happened since the subscription, starting from the number `0`.
  39. * @param {T} [defaultValue] The default value returned for missing indices.
  40. * @return {Observable} An Observable that emits a single item, if it is found.
  41. * Otherwise, will emit the default value if given. If not, then emits an error.
  42. * @method elementAt
  43. * @owner Observable
  44. */
  45. export function elementAt(index, defaultValue) {
  46. return (source) => source.lift(new ElementAtOperator(index, defaultValue));
  47. }
  48. class ElementAtOperator {
  49. constructor(index, defaultValue) {
  50. this.index = index;
  51. this.defaultValue = defaultValue;
  52. if (index < 0) {
  53. throw new ArgumentOutOfRangeError;
  54. }
  55. }
  56. call(subscriber, source) {
  57. return source.subscribe(new ElementAtSubscriber(subscriber, this.index, this.defaultValue));
  58. }
  59. }
  60. /**
  61. * We need this JSDoc comment for affecting ESDoc.
  62. * @ignore
  63. * @extends {Ignored}
  64. */
  65. class ElementAtSubscriber extends Subscriber {
  66. constructor(destination, index, defaultValue) {
  67. super(destination);
  68. this.index = index;
  69. this.defaultValue = defaultValue;
  70. }
  71. _next(x) {
  72. if (this.index-- === 0) {
  73. this.destination.next(x);
  74. this.destination.complete();
  75. }
  76. }
  77. _complete() {
  78. const destination = this.destination;
  79. if (this.index >= 0) {
  80. if (typeof this.defaultValue !== 'undefined') {
  81. destination.next(this.defaultValue);
  82. }
  83. else {
  84. destination.error(new ArgumentOutOfRangeError);
  85. }
  86. }
  87. destination.complete();
  88. }
  89. }
  90. //# sourceMappingURL=elementAt.js.map