头图

Look at the following code:

getSupportedDeliveryModes(): Observable<DeliveryMode[]> {
    return this.checkoutStore.pipe(
      select(CheckoutSelectors.getSupportedDeliveryModes),
      withLatestFrom(
        this.checkoutStore.pipe(
          select(getProcessStateFactory(SET_SUPPORTED_DELIVERY_MODE_PROCESS_ID))
        )
      ),
      tap(([, loadingState]) => {
        if (
          !(loadingState.loading || loadingState.success || loadingState.error)
        ) {
          this.loadSupportedDeliveryModes();
        }
      }),
      pluck(0),
      shareReplay({ bufferSize: 1, refCount: true })
    );
  }

The Observable object that calls withLatestFrom plays the role of leading data generation to downstream observers. The Observable object called as a parameter can only contribute new data, but cannot control the timing of data generation.

In other words, in the Spartacus example above, the CheckoutSelectors.getSupportedDeliveryModes Observable object is the leader in producing data downstream, while select(getProcessStateFactory(SET_SUPPORTED_DELIVERY_MODE_PROCESS_ID is only the contributor to the data fragment.

The syntax of line 54 in the figure below is a tuple, and the tuple is also an array, but the data types of each element do not necessarily have to be the same.

The loadingState on line 54 represents the state of setDeliveryModeProcess taken from the ngrx store. The semantics of line 55 is that if the status is loading or success, or error, do nothing, otherwise call loadSupportedDeliveryModes in line 58 to load mode.

Here we cleverly use withLatestFrom to introduce the loading state of delivery mode into the interaction of getSupportedDeliveryModes.

Look at another example:

protected buildRestoreSavedCartEvents<T>(
    mapping: ActionToEventMapping<T>
  ): () => void {
    const eventStream$ = this.getAction(mapping.action).pipe(
      switchMap((action) =>
        of(action).pipe(
          withLatestFrom(this.multiCartService.getCart(action.payload.cartId))
        )
      ),
      map(([action, cart]) =>
        createFrom(mapping.event as Type<T>, {
          ...action.payload,
          cartCode: cart.code,
          saveCartName: cart.name,
          saveCartDescription: cart.description,
          ...(cart.saveTime && { saveTime: cart.saveTime }),
        })
      )
    );

The type of the Observable object that calls withLatestFrom here is Action, which contains a field type of type string and a payload field of type any.

The contribution data is the input parameter passed into the withLatestFrom operator function, the type is the return parameter of this.multiCartService.getCart in line 146, and the type is Cart, as shown in the following figure:

Therefore, in the 149 lines of code downstream of the pipe operator, the input parameter of map is the tuple: [ action, cart], and the data types of the two elements are:

as well as:

It is worth mentioning that there are essential differences between combineLatest and withLatestFrom. In the former call, all Observables participating in the operation are of equal status. As long as any one of them changes, combineLatest will take out the last generated data from all input Observable objects, combine them into the data type of the array, and pass it to downstream.

More Jerry's original articles, all in: "Wang Zixi":


注销
1k 声望1.6k 粉丝

invalid