Exploring the Depths of Observables in Angular2 Guards

I have a Guardian overseeing a specific route. Within the canActivate method, I am trying to perform two HTTP requests, with the second request being dependent on the response of the first one. However, it seems like the second request is not being triggered, possibly due to the nested structure involving returning Observables.

1 canActivate(route: ActivatedRouteSnapshot,
2          state: RouterStateSnapshot) : Observable<boolean>|boolean {
3  return this.provider.getA().map(
4    dataA => {
5      return this.provider.getB().map(
6        dataB => {
7          return (dataB.allowed);
8        }
9      );
     }
   );  
 }

Both getA() and getB() functions return data in a similar format:

getA() : Observable<any> {
  return this.http.post(URL,payload).
                   map(response => response.json());

};

This code snippet is simplified, but assume that getA() and getB() are functioning correctly. While getA() is executed over the network when the Guardian is activated, getB() does not seem to be invoked at all. The issue appears to occur silently at line 5 in the debugger.

Additonally, TypeScript gives a warning message which may provide a solution, however, my understanding of Observables is limited for now:

Observable<Observable<boolean>>' is not assignable 
to type 'Observable<boolean>'

My assumption is that the Observables within each other are causing the delay in resolution, resulting in an indefinite waiting period without any errors. My simplistic view was that as long as an Observable eventually returns a boolean value (as seen in line 7), the subscriber would interpret it correctly.

Any insights or suggestions are welcome. Time for some rest...

Answer №1

For optimal efficiency, it is recommended to utilize the switchMap method in this scenario:

return this.provider.getA().switchMap(
  dataA => {
    return this.provider.getB().map(
      dataB => {
        return (dataB.allowed);
      }
    );
  }
);

Your current implementation results in an Observable of Observables. By utilizing switchMap, you are able to streamline this structure and emit the relevant items from B via A.

Answer №2

Update on solution provided by @j2l4e

The majority of RxJS operators are now pipeable, which means that using pipe() is necessary to avoid potential errors or warnings.

Improved solution utilizing pipe()

  canActivate(): boolean | Observable<boolean> | Observable<Observable<boolean>> {
    return this.httpClient
      .get('https://jsonplaceholder.typicode.com/todos')
      .pipe(
        switchMap((dataA: any) => {
          console.log('dataA :: ', dataA);
          return this.httpClient
            .get('https://jsonplaceholder.typicode.com/posts')
            .pipe(
              map((dataB: any) => {
                // include your logic here...
                console.log('data b', dataB);
                return false;
              })
            );
        })
      );
  }

For additional information, please consult the official documentation:

  1. https://rxjs.dev/guide/operators
  2. https://rxjs.dev/api/index/function/pipe
  3. https://rxjs.dev/api/operators/switchMap

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

Having trouble with importing and receiving the error message "Module 'clone' not found."

When trying to use clone.js in Angular 2, I imported it with import * as clone from 'clone'. It was listed in my package.json dependencies and successfully imported into node_modules. However, when viewing the output, I encountered the error mes ...

Issues with the execution of Typescript decorator method

Currently, I'm enrolled in the Mosh TypeScript course and came across a problem while working on the code. I noticed that the code worked perfectly in Mosh's video tutorial but when I tried it on my own PC and in an online playground, it didn&apo ...

Trouble with using the date pipe in Angular specifically for the KHMER language

<span>{{ value | date: 'E, dd/MM/yyyy':undefined:languageCode }}</span> I am facing a challenge where I need to identify the specific locale code for the KHMER language used in Cambodia. Despite trying various cod ...

Generate barcodes using Angular 2

Can anyone point me in the direction of an Angular 2 Barcode Generator capable of creating code 128 barcodes? I've been searching but haven't had any luck finding one. If you have any suggestions or can offer assistance, it would be greatly appr ...

What is the best way to retrieve a cookie sent from the server on a subdomain's domain within the client request headers using getServerSideProps

Currently, I have an express application using express-session running on my server hosted at api.example.com, along with a NextJS application hosted at example.com. While everything functions smoothly locally with the server setting a cookie that can be r ...

Error Encountered When Trying to Import Mocha for Typescript Unit Testing

Here's a snippet of code for testing a Typescript project using mocha chai. The test case is currently empty. import {KafkaConsumer} from '../infrastructure/delivery/kafka/kafka-consumer'; import {expect} from 'chai'; import {descr ...

Ways to streamline the type from typeof T down to T

One important aspect of my function is its signature, which looks like the following. waitMessage<T extends IIPCMessagesConstructors>(wantedMessageType: T): Promise<// ?? //> The definition of IIPCMessagesConstructors is crucial and consists ...

Avoid passing the ngrxStore object between separate custom elements

I am working with an Angular custom element that is exported as a web component. This custom element dispatches actions to a search state in order to perform a search functionality. The handling of these search state actions is carried out within an angula ...

The data type 'unknown' cannot be assigned to the type 'any[]', 'Iterable<any>', or (Iterable<any> & any[])

I have been working on creating a custom search filter in my Angular project, and it was functioning properly. However, I encountered an error in my Visual Studio Code. In my previous project, everything was working fine until I updated my CLI, which resul ...

How to access parent slider variables in an Angular component

I've developed a slider as the parent component with multiple child components. See the demo here: https://stackblitz.com/edit/angular-ivy-gcgxgh?file=src/app/slide2/slide2.component.html Slider in the parent component: <ng-container *ngFor=&quo ...

Issue with binding nested ViewModels/components in Knockoutjs using TypeScript does not resolve

Struggling with implementing a viewModel within another viewModel in knockout. Any assistance would be greatly appreciated. Using typescript and aiming to have a list of address controls, each with their individual viewmodel. Initially, the project functi ...

Error message 2339 - The property 'toggleExpand' is not recognized on the specified type 'AccHeaderContextProps | undefined'

When utilizing the context to share data, I am encountering a type error in TypeScript stating Property 'toggleExpand' does not exist on type 'AccHeaderContextProps | undefined'.ts(2339). However, all the props have been declared. inter ...

What is the best approach to manage the package versions of react, react-dom, @types/react, and @types/react-dom?

Recently, I decided to update the versions of react/react-dom in my project from 16.3.2 to 16.8.6 so that I could start using hooks. Surprisingly, after making some minor adjustments to my code, the update went smoothly. However, since we are utilizing ty ...

Different and Basic Designs for mat-table

Is there a way to customize the appearance of the material data table (mat-table) beyond the pre-built themes? I'm specifically interested in styles like table-striped, table-sm, or table-bordered from bootstrap 4. Is it possible to apply these style ...

Activate the location feature within an Ionic application

When using the function this.geolocation.getCurrentPosition() to retrieve the user's latitude and longitude, I encounter issues when the location setting is turned off. It does not provide any response in such cases. I am seeking a way to notify the u ...

Challenges encountered when assigning values in a form with Material UI, Formik, and Typescript

When attempting to set the 'role' and 'active' values on a form, I encountered a couple of issues. The first problem arises from the fact that the selectors' original values are not being properly set. These values are fetched in ...

Develop a TypeScript utility function for Prisma

Having trouble inferring the correct type for my utility function: function customUtilityFunction< P, R, A extends unknown[] >( prismaArgs /* Make "where" field optional as it is already defined inside findUnique method below */, fn: ( pris ...

Eliminate the routerLinkActive attribute that assigns two classes when the user switches to a different menu

As I develop a Web Application using Angular 6, I encounter an issue with implementing routerLink and routerLinkActive. While routerLink works properly, the routerLinkActive does not seem to function as expected. It retains the class within the tag even wh ...

Resolve the issue with automatically generating SCSS type definitions (style.d.ts) for Preact within a TypeScript webpack setup

Utilizing webpack with Preact 10.x (nearly identical to React) and TypeScript in the VSCode environment. Following an update from Node version 12 to version 14, there seems to be a problem where *.scss files no longer automatically generate their correspo ...

Conceal optional navigation bar options once a user has logged in - utilizing Angular 8

I need assistance with hiding certain links in my navbar once a user has logged in. Below are the current navbar menus: <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav ml-auto"> <li class="nav ...