Unraveling the secrets of Rxjs chaining

I have the following code that is functional and works as intended.

canActivate(route: ActivatedRouteSnapshot): Observable<UrlTree | boolean> {
  return new Observable<UrlTree | boolean>((observer) => {
    this._authorizedStore
      .select(selectProfile)
      .pipe(take(1))
      .subscribe((profile) => {
        if (!profile) {
          this._authorizedStore.dispatch(
            AuthorizedActions.loadProfile({ userId: this._authenticationApi.getUser().id }),
          );
        }

        this._authorizedStore
          .select(selectAuthorizedState)
          .pipe(first(state => !!state.profile))
          .subscribe((state) => {
            if (state.profile.profiles.length > 0) {
              observer.next(true);
            } else {
              observer.next(this.router.createUrlTree(['./settings']));
            }
            observer.complete();
          });
      });
  });
}

My goal is to find a more elegant and efficient way to achieve the same functionality. Essentially, I want to first check for the presence of a profile. If it doesn't exist, I need to trigger a request and then wait for its completion. It's worth mentioning that I'm using Ngrx, and if I don't use take(1) initially, it could lead to an infinite loop situation (no profile, make request, no profile, make request...).

Any suggestions on how to improve this process?

Answer №1

If you want to streamline your code, you have the option to utilize tap in conjunction with switchMap. See the example below:

this._authorizedStore
  .select(selectProfile)
  .pipe(
    take(1),
    tap(profile => {
      if (!profile) {
        this._authorizedStore.dispatch(
          AuthorizedActions.loadProfile({ userId: this._authenticationApi.getUser().id }),
        );
      }
    }),
    switchMap(profile => this._authorizedStore.select(selectAuthorizedState).pipe(first(state => !!state.profile)))
  )
  .subscribe(state => {
    if (state.profile.profiles.length > 0) {
      observer.next(true);
    } else {
      observer.next(this.router.createUrlTree(['./settings']));
    }
    observer.complete();
  });

You also have an alternative option where you can condense your entire code as shown below:

canActivate(route: ActivatedRouteSnapshot): Observable<UrlTree | boolean> {
  return this._authorizedStore
    .select(selectProfile)
    .pipe(
      take(1),
      tap(profile => {
        if (!profile) {
          this._authorizedStore.dispatch(
            AuthorizedActions.loadProfile({ userId: this._authenticationApi.getUser().id }),
          );
        }
      }),
      switchMap(profile => this._authorizedStore.select(selectAuthorizedState)),
      first(state => !!state.profile),
      map(state => state.profile.profiles.length > 0 ? true : this.router.createUrlTree(['./settings']))
    );
}

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

Validation of route parameters in Angular 4

Currently, I have a predefined route that includes a parameter called userID. { path: "edit/:userID", component: EditUserComponent, canActivate: [AuthGuard] }, Within the edit-user-component.ts file, the following logic is implemented: ...

Angular CLI build/serve/test commands task problem matcher in VS Code

In an attempt to set up VS code tasks for Angular CLI commands such as 'ng build', 'ng serve', and 'ng test', I want to generate a list of problems that can be easily navigated when running a CLI command. Currently, I execute ...

What is the process for incorporating a compiled JavaScript library into a TypeScript project?

In my Typescript project (ProjectA), I am utilizing several node packages. Additionally, I have a babel project (ProjectB) with a build configuration that supports output for multiple module definition standards such as amd, common.js, and esm. My questio ...

The latest version of IntelliJ Idea Ultimate, 2023.2.5, does not offer compatibility with the updated control flow features in Angular

I recently made the switch to Angular 17 in my project and noticed that Idea is not recognizing the new syntax in HTML templates. <mat-menu #menu="matMenu"> @for (menuItem of getData().menu.items; track menuItem) { & ...

Is the Bootstrap Carousel not automatically scrolling when navigating back in Angular?

Whenever I launch my Angular application, the image slider implemented using Bootstrap carousel functions properly. However, upon navigating to another view and returning to the image slider, it no longer auto-slides. Even though I can manually navigate th ...

Converting a text file to JSON in TypeScript

I am currently working with a file that looks like this: id,code,name 1,PRT,Print 2,RFSH,Refresh 3,DEL,Delete My task is to reformat the file as shown below: [ {"id":1,"code":"PRT","name":"Print"}, {" ...

Sending Angular POST requests with Date fields in a specific format for serialization

New to Angular and unsure of the best approach to serializing a Date property when adding an object to a POST request. Taking into account the sample class below: export class MyClass{ public dateProperty: Date; } The service code snippet is as follo ...

Steps for adjusting the length in the getRangeLabel function of mat paginator

@Injectable() export class MyCustomPaginatorIntl extends MatPaginatorIntl { public getRangeLabel = (page: number, pageSize: number, length: number): string => { if (length === 0 || pageSize === 0) { return `${ ...

I'm fascinated by the way well-known websites like The Guardian are utilizing Angular, as I often notice that when I click on links, the entire page reloads

As a beginner in Angular, I recently explored popular websites that implement Angular or React. I discovered sites like The Guardian, New York Times, and Netflix. However, most of these sites have links that open in new pages, while the remaining ones ut ...

How to submit a form nested within another form using React

I am working on a component called AddExpense.tsx which includes a form. The form should have the ability to add another category, which is a separate form stored in the AddCategory.tsx component. I am facing an issue where nesting these forms seems to br ...

What is the most effective way to retrieve the coordinates of a specific element in a React TSX component?

Using React alongside Typescript, I am trying to determine how to retrieve the coordinates of a sub-component within a React class that I have created. I came across this article: https://medium.com/@chung.andrew7/finding-the-absolute-positions-of-react-c ...

What is the most effective way to add cookies to the response object in a NestJS GraphQL application?

How can I save cookies in the response object of a NestJS GraphQL application? Here is the relevant code snippet: app.module.ts: GraphQLModule.forRoot<ApolloDriverConfig>({ autoSchemaFile: true, driver: ApolloDriver, cors: { ...

The command 'ng' is not valid in this context, please make sure it is being used correctly within the program or batch file

After attempting to install angular-cli with npm install -g, I hit a roadblock. Next, I attempted to add it to the PATH under Environment Variables but encountered no success. https://i.sstatic.net/uhuhN.png https://i.sstatic.net/zHGBk.png ...

What is the best way to identify if a variable in typescript is null?

Initially, I will perform an HTTP request to a URL in order to retrieve some data. { "data": { "user": { "name": "john", "other": [{ "a": 1, "b": 3 }] } } } My go ...

What is the solution for the warning "Solid's reactivity is broken when destructuring component props"?

Just starting out with SolidJS and encountering an issue with my UI setup import { render } from "solid-js/web"; import { createSignal, Show } from "solid-js"; import { createStore } from 'solid-js/store'; function Form() { ...

Aligning Description Item components horizontally in antdLearn how to easily horizontally align Description

Currently, I am utilizing the `antd` Description components. In this scenario, when there is no `title` for the items, the value should be aligned to the left. You can see an example of this alignment in the image below: https://i.sstatic.net/Ah70f.png I ...

Is Angular Signals on track to potentially supplant NgRx in some aspects?

After diving into Signals that are set to be introduced in Angular 16, I have already started coding with it and find it pretty amazing! I've heard rumors (and believe them) that Signals will likely replace most of the RxJS code, except for asynchron ...

The process of incorporating the dymo.framework into an Angular project

My Angular project is currently in need of importing dymo.connect.framework. However, I am facing some challenges as the SDK support provided by dymo only explains this process for JavaScript. I have also referred to an explanation found here. Unfortunate ...

The ActivatedRoute.routeConfig object appears to be empty in an Angular 2 project built with Angular-cli

Two projects I've created using angular-cli are working perfectly fine. However, in one of them, the routeConfig is showing as null and I can't figure out what's causing this issue. Both projects have identical package.json files, so there ...

Can someone provide guidance on utilizing the map function to iterate through intricate components in TypeScript?

I am facing a challenge while trying to iterate through a complex object containing 'inner objects'. When using the map function, I can only access one level below. How can I utilize map and TypeScript to loop through multiple levels below? Whene ...