Troubleshooting asynchronous problems with rxjs chaining within ngrx effects

@Effect({ dispatch: false })
public setJwtDataParcoursPage = this.actions$.pipe(
  ofType(INIT_FORM_SUCCESS_ACTION),
  map((action: InitFormSuccessAction) => action.payload),
  withLatestFrom(this.store.select(this._apiHeadersSelector.getJwt) as Observable<string>),
  switchMap(([payload, jwt]: [InitResponse, string]) => {
    const params = { jwt, userId: payload.jwt.user.id }
    return forkJoin([
      of(payload),
      iif(
        () => payload.subscriptionManagement,
        this.subscriptionService.getSubscriptionInfo(params).pipe(map(subscription => subscription.body)),
        of(null)
      )
    ])
  }),
  map(([payload, subscriptionData]) => {
    const subscriptionStatus = this.getValue(subscriptionData?.status, payload.jwt.env.subscriptionManagement);
    this._analyticsService.updateParcoursVars(payload, subscriptionStatus, "parcours", "form");
    this.store.dispatch(new GetSubscriptionInfoSuccessAction(subscriptionData))
  }),
  catchError(_ => {
    ...
    return of([])
  })
);

I have other tasks happening in //.

When payload.subscriptionManagement is false, everything works as expected. The chaining is not interrupted by other // tasks.

But when payload.subscriptionManagement is true, the code does not immediately reach the last part:

map([payload, subscriptionData] => {... 

It returns to this part later.

My question is, how can I modify this code to keep the chaining uninterrupted?

Update: I have tried the following approach:

@Effect({ dispatch: false })
public setJwtDataParcoursPage = this.actions$.pipe(
  ofType(INIT_FORM_SUCCESS_ACTION),
  map((action: InitFormSuccessAction) => action.payload),
  withLatestFrom(this.store.select(this._apiHeadersSelector.getJwt) as Observable<string>),
  switchMap(([payload, jwt]: [InitResponse, string]) => {
    const params = { jwt, userId: payload.jwt.user.id }
    return forkJoin([
      of(payload),
      iif(
        () => payload.jwt.env.subscriptionManagement,
        of(this.subscriptionService.getSubscriptionInfo(params)),
        of(null)
      )
    ])
  }),
  map(([payload, subscriptionData]) => {
    subscriptionData.subscribe(subscription => {
      const subscriptionStatus = this.getValue(subscription?.body.status, payload.jwt.env.subscriptionManagement);
      this._analyticsService.updateParcoursVars(payload, subscriptionStatus, "parcours", "form");
      this.store.dispatch(new GetSubscriptionInfoSuccessAction(subscription.body))
    })
}),

Now, when payload.subscriptionManagement is true, it enters the

map([payload, subscriptionData] => {
section but the effect is interrupted when subscribe.

Answer №1

It appears that the situation may be unnecessarily complex. The forkJoin might not be essential in this case. Instead of mapping after the switchMap, it could be beneficial to utilize the tap function on the observable being switched to. Since you are not dispatching from the effect in all scenarios, using map may not be necessary. While the code sample provided may not be flawless, it should help steer you in the right direction.

@Effect({ dispatch: false })
public setJwtDataParcoursPage = this.actions$.pipe(
  ofType(INIT_FORM_SUCCESS_ACTION),
  map((action: InitFormSuccessAction) => action.payload),
  concatLatestFrom() => (this.store.select(this._apiHeadersSelector.getJwt) as Observable<string>), 
  switchMap(([payload, jwt]: [InitResponse, string]) => {
    const params = { jwt, userId: payload.jwt.user.id }

    if (!payload.subscriptionManagement) {
      const subscriptionStatus = this.getValue(null, payload.jwt.env.subscriptionManagement);
      this._analyticsService.updateParcoursVars(payload, subscriptionStatus, "parcours", "form");
      return;
    }
    return this.subscriptionService.getSubscriptionInfo(params).pipe(
      map(subscription => subscription.body),
      tap((subscriptionData) => {
        const subscriptionStatus = this.getValue(subscriptionData?.body.status, payload.jwt.env.subscriptionManagement);
        this._analyticsService.updateParcoursVars(payload, subscriptionStatus, "parcours", "form");
        this.store.dispatch(new GetSubscriptionInfoSuccessAction(subscriptionData?.body))
      })
    );
  }),
  catchError(_ => {
    ...
    return EMPTY
  })
);

Furthermore, it is advisable to use concatLatestFrom. It is now also recommended to incorporate createEffect.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to set up a universal type definition in TypeScript version 2 and above?

I have a collection of straightforward .ts files, not part of any projects but standalone .ts scripts. They implement certain node.js features. Both TypeScript and node type definitions are set up through the following commands: npm install -g typescript ...

Tips for bringing in Cassandra driver types in TypeScript?

In the documentation for the Cassandra driver, they provide code examples like this: const Uuid = require('cassandra-driver').types.Uuid; const id = Uuid.random(); However, when attempting to use this in Visual Studio Code, the Uuid class type ...

I attempted to implement a CSS and Typescript animation for a sliding effect, but unfortunately, it isn't functioning

So I'm encountering an issue with this unique ts code: {/* Mobile Menu */} <div className="lg:hidden"> <button className="flex items-center w-8" onClick={toggleMenu}> {isMobileMenuOpen ? ( ...

Resolving the CORS predicament caused by the ionic/angular's HTTP interceptor

I am currently using Ionic for both web and mobile development. However, I have encountered a CORS issue when integrating it with an HTTPS URL. Interestingly, the issue seems to be resolved after removing the HTTP interceptor. Nevertheless, I am seeking a ...

What is the reason behind decorators needing to utilize apply(this) on a function?

I've been delving into the realm of JavaScript and exploring decorator code. One thing I've noticed is that when looking at decorator code like the example below, the input function always applies to 'this' even though it doesn't a ...

Ways to show an object by comparing its object ID to the ID received from the server

I have a collection of objects structured as follows: defined in FruitModel.ts export interface ColorByFruit{ Id : number; name : string; color : string; } const Fruits: ColorByFruit[] = [ {Id:1, name:"Apple", color:&quo ...

Using Angular 2 to efficiently recycle a subcomponent with the same form across multiple parent components while maintaining its state

I've been struggling to find someone with the same issue as me, even though the title may seem familiar. Perhaps I need help rephrasing my question? Here's an explanation: Use case: I have multiple routes (only 2 in the example below) set up fo ...

Show the Search Results from Angular 2 in a Separate Component

When I search, the names are displayed on a suggestion list without any issues because they are not in a separate component. Search HTML <input type="text" placeholder="Search" (keyup)="getSuggestion($event.target.value)"> <div class="suggest ...

What is the best way to effectively use combinedLatestWith?

https://stackblitz.com/edit/angular-ivy-s2ujmr?file=src/app/country-card/country-card.component.html I am currently working on implementing a search bar in Angular that filters the "countries$" Observable based on user input. My approach involves creatin ...

What is the best way to trigger a method after an old component has been removed from the DOM while navigating within Angular

I am facing a challenge where I need to execute a method on ComponentB after a routerLink is clicked, causing the navigation from ComponentA to ComponentB. It is crucial that this method is triggered only after the entire navigation process is complete (i. ...

Issue with Angular 5 Application - "Implementations cannot be declared in ambient contexts"

Recently in my Angular 5 project, I started encountering an issue with the observable object. Everything was working smoothly until about a week ago when I began receiving this error message: ERROR in node_modules/rxjs/Observable.d.ts(20,31): error TS1183 ...

Customize the style of Angular Material within an Angular component

In my Angular component, I am utilizing Material 2's <md-input-container>. I am looking to customize a specific class, such as .mat-input-wrapper, that is originally defined in Angular Material. However, my intention is for this customization to ...

What is the method for placing a title in the initial column with the help of v-simple-table from Vuetify.js?

I am interested in using the v-simple-table UI component from Vuetify.js to create a table similar to the one shown below. https://i.sstatic.net/QNdpJ.png After creating the code in codesandbox and previewing the output, I noticed that the title is not a ...

Issue with InversifyJS @multiInject: receiving an error stating "ServiceIdentifier has an ambiguous match"

Having an issue with inversifyJs while trying to implement dependency injection in my TypeScript project. Specifically, when using the @multiInject decorator, I keep receiving the error "Ambiguous match found for serviceIdentifier". I've been referenc ...

Interactive 3D model movable within designated area | R3F

I am currently facing a challenge in limiting the drag area of my 3D models to the floor within my FinalRoom.glb model. After converting it to tsx using gltfjsx, I obtained the following code: import * as THREE from "three"; import React, { useRe ...

Leverage the power of react-redux useSelector with the precision of TypeScript

When attempting to utilize the new useSelector hook (shown in the example below) from react-redux in TypeScript, an error is encountered indicating that the function does not exist: Module '"../../../node_modules/@types/react-redux"' has no expo ...

What is the best way to loop through the keys of a generic object in TypeScript?

When I come across a large object of unknown size, my usual approach is to iterate over it. In the past, I've used generators and custom Symbol.iterator functions to make these objects iterable with a for..of loop. However, in the ever-evolving world ...

IE11 causing issues with Bootstrap/Angular dropdown functionality

Is there a workaround for the issue with the selected menu item not showing in IE11 for this simple drop-down? <div class="form-group program-container"> <select class="form-control container-fluid" (change)="onChooseMe ...

Does SharePoint Online support the .webmanifest format? What is the process for creating a Progressive Web Application in SharePoint Online using a supported webmanifest file?

Currently, I am in the process of developing a Progressive Web Application for SharePoint Online by utilizing the Angular 8 PWA build. The service worker and application are running smoothly; however, I have encountered an issue with loading the webmanifes ...

What is the best way to format a User object into JSON before sending it to an API endpoint?

Encountering an error 400 when attempting to submit a POST request. "$.User": [ "The JSON value could not be converted to WebApi.Models.User. Path: $.User | LineNumber: 5 | BytePositionInLine: 19." ] } Detailing my Order Model with ...