rxjs#MonoTypeOperatorFunction TypeScript Examples

The following examples show how to use rxjs#MonoTypeOperatorFunction. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: backend_srv.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
private toDataSourceRequestFailureStream = (
    options: BackendSrvRequest
  ): MonoTypeOperatorFunction<FetchResponse> => inputStream =>
    inputStream.pipe(
      filter(response => response.ok === false),
      mergeMap(response => {
        const { status, statusText, data } = response;
        const fetchErrorResponse: ErrorResponse = { status, statusText, data };
        return throwError(fetchErrorResponse);
      }),
      retryWhen((attempts: Observable<any>) =>
        attempts.pipe(
          mergeMap((error, i) => {
            const requestIsLocal = !options.url.match(/^http/);
            const firstAttempt = i === 0 && options.retry === 0;

            // First retry, if loginPing returns 401 this retry sequence will abort with throwError and user is logged out
            if (requestIsLocal && firstAttempt && error.status === 401) {
              return from(this.loginPing()).pipe(
                catchError(err => {
                  if (err.status === 401) {
                    this.dependencies.logout();
                    return throwError(err);
                  }
                  return throwError(err);
                })
              );
            }

            return throwError(error);
          })
        )
      )
    );
Example #2
Source File: angular-zone-message-client-decorator.snippets.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 6 votes vote down vote up
// end::intent-client-decorator[]

// tag::emit-inside-angular[]
function synchronizeWithAngular<T>(zone: NgZone): MonoTypeOperatorFunction<T> {
  return pipe(
    subscribeInside(continueFn => zone.runOutsideAngular(continueFn)),
    observeInside(continueFn => zone.run(continueFn)),
  );
}
Example #3
Source File: keyboard-event-dispatcher.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Applies keystroke flags on each keyboard event emitted by the source Observable.
 *
 * Note that `preventDefault()` has to be invoked on the original event, which has its `isTrusted` flag set to `true`.
 *
 * For more information about trusted events
 * @see https://www.w3.org/TR/DOM-Level-3-Events/#trusted-events
 * @see https://www.chromestatus.com/features#istrusted
 *
 * @internal
 */
function applyKeystrokeFlags(flags: KeystrokeFlags | undefined): MonoTypeOperatorFunction<KeyboardEvent> {
  return tap(keystrokeEvent => {
    if (flags?.preventDefault) {
      keystrokeEvent.preventDefault();
    }
  });
}
Example #4
Source File: broker-gateway.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Replaces `Map` objects contained in the message with a `Map` object of the current JavaScript realm.
 *
 * Data sent from one JavaScript realm to another is serialized with the structured clone algorithm.
 * Although the algorithm supports the `Map` data type, a deserialized map object cannot be checked to be instance of `Map`.
 * This is most likely because the serialization takes place in a different realm.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
 * @see http://man.hubwiz.com/docset/JavaScript.docset/Contents/Resources/Documents/developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm.html
 * @internal
 */
function fixMapObjects<T extends Message>(): MonoTypeOperatorFunction<MessageEvent<MessageEnvelope<T>>> {
  return map((event: MessageEvent<MessageEnvelope<T>>): MessageEvent<MessageEnvelope<T>> => {
    const envelope: MessageEnvelope = event.data;
    envelope.message.headers = new Map(envelope.message.headers || []);

    if (envelope.channel === MessagingChannel.Intent) {
      const intentMessage = envelope.message as IntentMessage;
      intentMessage.intent.params = new Map(intentMessage.intent.params || []);
    }
    if (envelope.channel === MessagingChannel.Topic) {
      const topicMessage = envelope.message as TopicMessage;
      topicMessage.params = new Map(topicMessage.params || []);
    }
    return event;
  });
}
Example #5
Source File: message-client.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Returns an Observable that mirrors the source Observable as long as there is at least one subscriber subscribed to the
 * given topic. When the subscription count on the given topic drops to zero, the returned Observable completes. If there
 * is no topic subscription present at the time when subscribing to the Observable, then it completes immediately.
 *
 * This operator is similar to the RxJS {@link takeUntil} operator, but accepts a topic instead of a notifier Observable.
 *
 * @category Messaging
 */
export function takeUntilUnsubscribe<T>(topic: string): MonoTypeOperatorFunction<T> {
  return takeUntil(Beans.get(MessageClient).subscriberCount$(topic).pipe(first(count => count === 0)));
}
Example #6
Source File: backend_srv.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
private toFailureStream = (options: BackendSrvRequest): MonoTypeOperatorFunction<FetchResponse> => inputStream =>
    inputStream.pipe(
      filter(response => response.ok === false),
      mergeMap(response => {
        const { status, statusText, data } = response;
        const fetchErrorResponse: ErrorResponse = { status, statusText, data };
        return throwError(fetchErrorResponse);
      }),
      retryWhen((attempts: Observable<any>) =>
        attempts.pipe(
          mergeMap((error, i) => {
            const firstAttempt = i === 0 && options.retry === 0;

            if (error.status === 401 && this.dependencies.contextSrv.user.isSignedIn && firstAttempt) {
              return from(this.loginPing()).pipe(
                catchError(err => {
                  if (err.status === 401) {
                    this.dependencies.logout();
                    return throwError(err);
                  }
                  return throwError(err);
                })
              );
            }

            return throwError(error);
          })
        )
      )
    );
Example #7
Source File: message-broker.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Catches and logs errors, and resubscribes to the source observable.
 *
 * @ignore
 */
function catchErrorAndRetry<T>(): MonoTypeOperatorFunction<T> {
  return catchError((error, caught) => {
    Beans.get(Logger).error('[UnexpectedError] An unexpected error occurred.', error);
    return caught;
  });
}
Example #8
Source File: app-details.component.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Filters {@link NavigationEnd} events matching the given route.
 */
function matchesRoute(router: Router, route: ActivatedRoute): MonoTypeOperatorFunction<NavigationEnd> {
  return filter((navigationEnd: NavigationEnd): boolean => {
    const rootUrlSegmentGroup = router.parseUrl(navigationEnd.url).root;

    let urlSegmentGroupUnderTest: UrlSegmentGroup = null;
    return route.snapshot.pathFromRoot.every(activatedRoute => {
      urlSegmentGroupUnderTest = urlSegmentGroupUnderTest ? urlSegmentGroupUnderTest.children[activatedRoute.outlet] : rootUrlSegmentGroup;
      return Arrays.isEqual(activatedRoute.url.map(segment => segment.toString()), urlSegmentGroupUnderTest.segments.map(segment => segment.toString()));
    });
  });
}
Example #9
Source File: debounce-with-backoff-while.ts    From js-client with MIT License 6 votes vote down vote up
debounceWithBackoffWhile = <T>({
	initialDueTime,
	step,
	maxDueTime,
	predicate,
}: {
	initialDueTime: number;
	step: number;
	maxDueTime: number;
	predicate: (value: T) => boolean;
}): MonoTypeOperatorFunction<T> => {
	const nextDueTime = (lastDueTime: number, value: T) => {
		if (!predicate(value)) {
			return initialDueTime;
		}
		return Math.min(lastDueTime + step, maxDueTime);
	};

	return (source: Observable<T>): Observable<T> =>
		source.pipe(debounce(rxjsDynamicDuration(nextDueTime, initialDueTime)));
}
Example #10
Source File: filter-behavior.ts    From s-libs with MIT License 6 votes vote down vote up
/**
 * Works like `filter()`, but always lets through the first emission for each new subscriber. This makes it suitable for subscribers that expect the observable to behave like a `BehaviorSubject`, where the first emission is processed synchronously during the call to `subscribe()` (such as the `async` pipe in an Angular template).
 *
 * ```
 * source:                   |-false--true--false--true--false--true-|
 * filterBehavior(identity): |-false--true---------true---------true-|
 * filterBehavior(identity):        |-true---------true---------true-|
 * filterBehavior(identity):              |-false--true---------true-|
 * ```
 */
export function filterBehavior<T>(
  predicate: Predicate<T>,
): MonoTypeOperatorFunction<T> {
  return createOperatorFunction<T>((subscriber, destination) => {
    let firstValue = true;
    subscriber.next = (value): void => {
      if (firstValue) {
        destination.next(value);
        firstValue = false;
        return;
      }

      try {
        if (predicate(value)) {
          destination.next(value);
        }
      } catch (ex) {
        destination.error(ex);
      }
    };
  });
}
Example #11
Source File: cache.ts    From s-libs with MIT License 6 votes vote down vote up
/**
 * 1. Caches the last value emitted to give to new subscribers (without running any upstream pipe operators)
 * 2. Manages all subscribers directly, without passing subscriptions up the stream.
 *
 * This is very similar to `shareReplay(1)`, except that once all subscribers unsubscribe this also unsubscribes from the upstream observable.
 *
 * ```ts
 * const source = new BehaviorSubject(1000);
 * const result = source.pipe(expensiveComputation(), cache());
 * source.subscribe(); // expensiveComputation(1000) runs
 * source.subscribe(); // the cached result is used
 * source.next(2000); // expensiveComputation(2000) runs once, emitted to both subscribers
 * ```
 */
export function cache<T>(): MonoTypeOperatorFunction<T> {
  return (source: Observable<T>): Observable<T> => {
    let middleMan: ReplaySubject<T> | undefined;
    let upstreamSubscription: Subscription;
    return new Observable<T>((subscriber) => {
      if (!middleMan) {
        middleMan = new ReplaySubject<T>(1);
        upstreamSubscription = source.subscribe(middleMan);
      }

      const subscription = middleMan.subscribe(subscriber);

      // teardown logic
      return (): void => {
        subscription.unsubscribe();
        if (middleMan!.observers.length === 0) {
          upstreamSubscription.unsubscribe();
          middleMan = undefined;
        }
      };
    });
  };
}
Example #12
Source File: distinct-until-keys-changed.ts    From s-libs with MIT License 6 votes vote down vote up
/**
 * Allows items through whose keys are distinct from the previous item.
 *
 * ```
 * source:                     |-{a:1,b:2}--{a:2,b:3}--{a:2,c:3}--{b:3}--{b:4}-|
 * distinctUntilKeysChanged(): |-{a:1,b:2}-------------{a:2,c:3}--{b:3}--------|
 * ```
 */
export function distinctUntilKeysChanged<
  T extends object,
>(): MonoTypeOperatorFunction<T> {
  let lastKeySet: Set<string | keyof T> | undefined;
  return filter((value) => {
    const keySet = new Set(keys(value));
    if (lastKeySet && isSetEqual(keySet, lastKeySet)) {
      return false;
    }

    lastKeySet = keySet;
    return true;
  });
}
Example #13
Source File: operators.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 5 votes vote down vote up
/** @ignore */
export function filterByMessageHeader<T extends Message>(header: {key: string; value: any}): MonoTypeOperatorFunction<MessageEvent<MessageEnvelope<T>>> {
  return filter((event: MessageEvent<MessageEnvelope<T>>): boolean => {
    const messageHeaders = event.data.message.headers;
    return messageHeaders.has(header.key) && messageHeaders.get(header.key) === header.value;
  });
}
Example #14
Source File: backend_srv.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
private handleStreamCancellation = (
    options: BackendSrvRequest,
    resultType: CancellationType
  ): MonoTypeOperatorFunction<FetchResponse | DataSourceSuccessResponse | SuccessResponse> => inputStream =>
    inputStream.pipe(
      takeUntil(
        this.inFlightRequests.pipe(
          filter(requestId => {
            let cancelRequest = false;
            if (options && options.requestId && options.requestId === requestId) {
              // when a new requestId is started it will be published to inFlightRequests
              // if a previous long running request that hasn't finished yet has the same requestId
              // we need to cancel that request
              cancelRequest = true;
            }
            return cancelRequest;
          })
        )
      ),
      // when a request is cancelled by takeUntil it will complete without emitting anything so we use throwIfEmpty to identify this case
      // in throwIfEmpty we'll then throw an cancelled error and then we'll return the correct result in the catchError or rethrow
      throwIfEmpty(() => ({
        cancelled: true,
      })),
      catchError(err => {
        if (!err.cancelled) {
          return throwError(err);
        }

        if (resultType === CancellationType.dataSourceRequest) {
          return of({
            data: [],
            status: this.HTTP_REQUEST_CANCELED,
            statusText: 'Request was aborted',
            config: options,
          });
        }

        return of([]);
      })
    );
Example #15
Source File: skip-after.ts    From s-libs with MIT License 5 votes vote down vote up
/**
 * Causes the next value in the pipe to be skipped after `skip$` emits a value. For example:
 *
 * ```
 * source: -1-----2-----3-----4-----5-|
 * skip$:  ----0----------0-0----------
 *
 * result: -1-----------3-----------5-|
 * ```
 * ```ts
 * const source = new Subject();
 * const skip$ = new Subject();
 * const result = source.pipe(skipAfter(skip$));
 *
 * source.next(1); // result emits `1`
 *
 * skip$.next();
 * source.next(2); // result does not emit
 * source.next(3); // result emits `3`
 *
 * skip$.next();
 * skip$.next();
 * source.next(4); // result does not emit
 * source.next(5); // result emits `5`
 * ```
 */
export function skipAfter<T>(
  skip$: Observable<any>,
): MonoTypeOperatorFunction<T> {
  return createOperatorFunction<T>((subscriber, destination) => {
    let skipNext = false;
    subscriber.add(
      skip$.subscribe({
        next: () => {
          skipNext = true;
        },
        error: bindKey(destination, 'error'),
      }),
    );
    subscriber.next = (value): void => {
      if (skipNext) {
        skipNext = false;
      } else {
        destination.next(value);
      }
    };
  });
}
Example #16
Source File: log-values.ts    From s-libs with MIT License 5 votes vote down vote up
/**
 * Logs values, errors and completion to the console, and passes them all along unchanged.
 *
 * ```ts
 * of(1, 2).pipe(logValues()).subscribe();
 * // prints using console.log:
 * // [value] 1
 * // [value] 2
 * // [complete]
 *
 * of(1, 2).pipe(logValues("my number", "debug")).subscribe();
 * // prints using console.debug:
 * // [value] my number 1
 * // [value] my number 2
 * // [complete] my number
 *
 * throwError("boo").pipe(logValues("pipe says", "warn")).subscribe();
 * // prints using console.warn:
 * // [error] pipe says boo
 * ```
 */
export function logValues<T>(
  prefix?: string,
  level: 'debug' | 'trace' | 'info' | 'log' | 'warn' | 'error' = 'log',
): MonoTypeOperatorFunction<T> {
  return tap<T>({
    next: makeLogFn('[value]'),
    error: makeLogFn('[error]'),
    complete: makeLogFn('[complete]'),
  });

  function makeLogFn(...prefixes: string[]): (value?: any) => void {
    if (prefix !== undefined) {
      prefixes.push(prefix);
    }
    return (...values: any[]): void => {
      console[level](...prefixes, ...values);
    };
  }
}
Example #17
Source File: delay-on-microtask-queue.ts    From s-libs with MIT License 5 votes vote down vote up
/**
 * Delays the emission of items from the source Observable using the microtask queue.
 */
export function delayOnMicrotaskQueue<T>(): MonoTypeOperatorFunction<T> {
  return delay<T>(0, asapScheduler);
}
Example #18
Source File: wrapped-control-superclass.ts    From s-libs with MIT License 5 votes vote down vote up
#handleError<T>(): MonoTypeOperatorFunction<T> {
    return flow(
      tap<T>({ error: bindKey(this.#errorHandler, 'handleError') }),
      retry(),
    );
  }
Example #19
Source File: operators.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 5 votes vote down vote up
/** @ignore */
export function filterByOrigin(origin: string): MonoTypeOperatorFunction<MessageEvent> {
  return filter((event: MessageEvent): boolean => {
    return event.origin === origin;
  });
}
Example #20
Source File: messaging.model.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Returns an Observable that mirrors the source Observable unless receiving a message with
 * a response status code greater than or equal to 400. Then, the stream will end with an
 * {@link RequestError error} and the source Observable unsubscribed.
 *
 * When receiving a message with the response status code {@link ResponseStatusCodes.TERMINAL},
 * the Observable emits this message and completes.
 *
 * If a message does not include a response status code, the message is emitted as is.
 *
 * Note that this operator is installed in {@link MessageClient.request$} and {@link IntentClient.request$}.
 *
 * @category Messaging
 */
export function throwOnErrorStatus<BODY>(): MonoTypeOperatorFunction<TopicMessage<BODY>> {
  return pipe(
    mergeMap((message: TopicMessage<BODY>): Observable<TopicMessage<BODY>> => {
      const status = message.headers.get(MessageHeaders.Status) ?? ResponseStatusCodes.OK;
      if (status < 400) {
        return of(message); // 1xx: informational responses, 2xx: successful responses, 4xx: client errors, 5xx: server errors
      }

      if (typeof message.body === 'string') {
        const messageBody: string = message.body;
        return throwError(() => new RequestError(messageBody, status, message));
      }

      switch (status) {
        case ResponseStatusCodes.BAD_REQUEST: {
          return throwError(() => new RequestError('The receiver could not understand the request due to invalid syntax.', status, message));
        }
        case ResponseStatusCodes.NOT_FOUND: {
          return throwError(() => new RequestError('The receiver could not find the requested resource.', status, message));
        }
        case ResponseStatusCodes.ERROR: {
          return throwError(() => new RequestError('The receiver encountered an internal error.', status, message));
        }
        default: {
          return throwError(() => new RequestError('Request error.', status, message));
        }
      }
    }),
    takeWhile((message: TopicMessage<BODY>) => {
      return message.headers.get(MessageHeaders.Status) !== ResponseStatusCodes.TERMINAL;
    }, true),
    filter((message: TopicMessage<BODY>) => {
      const isTerminalMessage = message.headers.get(MessageHeaders.Status) === ResponseStatusCodes.TERMINAL;
      return (!isTerminalMessage || message.body !== undefined);
    }),
  );
}
Example #21
Source File: message-broker.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Passes only messages originating from trusted and registered clients.
 *
 * @ignore
 */
function checkOriginTrusted<T extends Message>(): MonoTypeOperatorFunction<MessageEvent<MessageEnvelope<T>>> {
  return mergeMap((event: MessageEvent<MessageEnvelope<T>>): Observable<MessageEvent<MessageEnvelope<T>>> => {
    const envelope: MessageEnvelope = event.data;
    const messageId = envelope.message.headers.get(MessageHeaders.MessageId);
    const clientId = envelope.message.headers.get(MessageHeaders.ClientId);
    const client = Beans.get(ClientRegistry).getByClientId(clientId)!;

    // Assert client registration.
    if (!client) {
      if (event.source !== null) {
        const sender = new MessageTarget(event);
        const error = `[MessagingError] Message rejected: Client not registered [origin=${event.origin}]`;
        sendDeliveryStatusError(sender, messageId, error);
      }
      return EMPTY;
    }

    // Assert source origin.
    if (event.origin !== client.application.messageOrigin) {
      if (event.source !== null) {
        const sender = new MessageTarget(event);
        const error = `[MessagingError] Message rejected: Wrong origin [actual=${event.origin}, expected=${client.application.messageOrigin}, application=${client.application.symbolicName}]`;
        sendDeliveryStatusError(sender, messageId, error);
      }
      return EMPTY;
    }

    // Assert source window unless the request is stale, i.e., if the origin window has been closed or a site with a different origin has been loaded.
    // We still process stale requests to enable proper disconnection of the client, such as delivery of messages published by the client during shutdown,
    // but mark the client as stale and queue it for later removal.
    if (event.source === null) {
      client.markStaleAndQueueForRemoval();
    }
    else if (event.source !== client.window) {
      const sender = new MessageTarget(event);
      const error = `[MessagingError] Message rejected: Wrong window [origin=${event.origin}]`;
      sendDeliveryStatusError(sender, messageId, error);
      return EMPTY;
    }

    return of(event);
  });
}
Example #22
Source File: ng-zone-decorators.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 5 votes vote down vote up
function synchronizeWithAngular<T>(zone: NgZone): MonoTypeOperatorFunction<T> {
  return pipe(
    subscribeInside(continueFn => zone.runOutsideAngular(continueFn)),
    observeInside(continueFn => zone.run(continueFn)),
  );
}
Example #23
Source File: ng-zone-decorators.ts    From scion-microfrontend-platform with Eclipse Public License 2.0 5 votes vote down vote up
function synchronizeWithAngular<T>(zone: NgZone): MonoTypeOperatorFunction<T> {
  return pipe(
    subscribeInside(continueFn => zone.runOutsideAngular(continueFn)),
    observeInside(continueFn => zone.run(continueFn)),
  );
}