Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

single.ts 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import { Observable } from '../Observable';
  2. import { Operator } from '../Operator';
  3. import { Subscriber } from '../Subscriber';
  4. import { EmptyError } from '../util/EmptyError';
  5. import { Observer, MonoTypeOperatorFunction, TeardownLogic } from '../types';
  6. /**
  7. * Returns an Observable that emits the single item emitted by the source Observable that matches a specified
  8. * predicate, if that Observable emits one such item. If the source Observable emits more than one such item or no
  9. * items, notify of an IllegalArgumentException or NoSuchElementException respectively. If the source Observable
  10. * emits items but none match the specified predicate then `undefined` is emitted.
  11. *
  12. * <span class="informal">Like {@link first}, but emit with error notification if there is more than one value.</span>
  13. * ![](single.png)
  14. *
  15. * ## Example
  16. * emits 'error'
  17. * ```ts
  18. * import { range } from 'rxjs';
  19. * import { single } from 'rxjs/operators';
  20. *
  21. * const numbers = range(1,5).pipe(single());
  22. * numbers.subscribe(x => console.log('never get called'), e => console.log('error'));
  23. * // result
  24. * // 'error'
  25. * ```
  26. *
  27. * emits 'undefined'
  28. * ```ts
  29. * import { range } from 'rxjs';
  30. * import { single } from 'rxjs/operators';
  31. *
  32. * const numbers = range(1,5).pipe(single(x => x === 10));
  33. * numbers.subscribe(x => console.log(x));
  34. * // result
  35. * // 'undefined'
  36. * ```
  37. *
  38. * @see {@link first}
  39. * @see {@link find}
  40. * @see {@link findIndex}
  41. * @see {@link elementAt}
  42. *
  43. * @throws {EmptyError} Delivers an EmptyError to the Observer's `error`
  44. * callback if the Observable completes before any `next` notification was sent.
  45. * @param {Function} predicate - A predicate function to evaluate items emitted by the source Observable.
  46. * @return {Observable<T>} An Observable that emits the single item emitted by the source Observable that matches
  47. * the predicate or `undefined` when no items match.
  48. *
  49. * @method single
  50. * @owner Observable
  51. */
  52. export function single<T>(predicate?: (value: T, index: number, source: Observable<T>) => boolean): MonoTypeOperatorFunction<T> {
  53. return (source: Observable<T>) => source.lift(new SingleOperator(predicate, source));
  54. }
  55. class SingleOperator<T> implements Operator<T, T> {
  56. constructor(private predicate?: (value: T, index: number, source: Observable<T>) => boolean,
  57. private source?: Observable<T>) {
  58. }
  59. call(subscriber: Subscriber<T>, source: any): TeardownLogic {
  60. return source.subscribe(new SingleSubscriber(subscriber, this.predicate, this.source));
  61. }
  62. }
  63. /**
  64. * We need this JSDoc comment for affecting ESDoc.
  65. * @ignore
  66. * @extends {Ignored}
  67. */
  68. class SingleSubscriber<T> extends Subscriber<T> {
  69. private seenValue: boolean = false;
  70. private singleValue: T;
  71. private index: number = 0;
  72. constructor(destination: Observer<T>,
  73. private predicate?: (value: T, index: number, source: Observable<T>) => boolean,
  74. private source?: Observable<T>) {
  75. super(destination);
  76. }
  77. private applySingleValue(value: T): void {
  78. if (this.seenValue) {
  79. this.destination.error('Sequence contains more than one element');
  80. } else {
  81. this.seenValue = true;
  82. this.singleValue = value;
  83. }
  84. }
  85. protected _next(value: T): void {
  86. const index = this.index++;
  87. if (this.predicate) {
  88. this.tryNext(value, index);
  89. } else {
  90. this.applySingleValue(value);
  91. }
  92. }
  93. private tryNext(value: T, index: number): void {
  94. try {
  95. if (this.predicate(value, index, this.source)) {
  96. this.applySingleValue(value);
  97. }
  98. } catch (err) {
  99. this.destination.error(err);
  100. }
  101. }
  102. protected _complete(): void {
  103. const destination = this.destination;
  104. if (this.index > 0) {
  105. destination.next(this.seenValue ? this.singleValue : undefined);
  106. destination.complete();
  107. } else {
  108. destination.error(new EmptyError);
  109. }
  110. }
  111. }