Executing a secondary API based on the data received from the initial API call

Currently, I am diving into the world of RxJS. In my project, I am dealing with 2 different APIs where I need to fetch data from the first API and then make a call to the second API based on that data. Originally, I implemented this logic using the subscribe() method as shown below:

checkPermission(permissionName: string): Observable<boolean> {
    this.checkCompanySettingForPermission(
      this.pageLevelCompanySettingName
    ).subscribe(res => {
      const shouldCheck = res.Value;
      if (shouldCheck.toLowerCase() === "true") {
        this.hasPermission(permissionName).subscribe(res => {
          this.$permissionSub.next(res.permission);
        });
      } else {
        this.$permissionSub.next(true);
      }
    });
    return this.$permissionSub.asObservable();
  }

However, I'm now looking for a way to avoid nesting subscribe() methods within each other. Is there any RxJS operator that can help me achieve this?

I attempted to use switchMap() but encountered numerous syntax errors in the process. Any guidance or assistance would be greatly appreciated.

Answer №1

To achieve this functionality, you can utilize one of the Higher-Order RxJS mapping operators such as: switchMap, mergeMap, concatMap to combine the source observable with a new one.

In your specific case, using switchMap or mergeMap, we should ultimately return a new observable at the end to be merged with the original checkCompanySettingForPermission observable.

If the condition is met, we will return the this.hasPermission observable; otherwise, we will return a new observable using the of function with the necessary value (true in this scenario).

You can implement it like this:

checkPermission(permissionName: string): Observable<boolean> {
  this.checkCompanySettingForPermission(this.pageLevelCompanySettingName)
    .pipe(
      switchMap(res => {
        const shouldCheck = res.Value;
        if (shouldCheck.toLowerCase() === 'true') {
          // switchMap to the new observable and then map it to return only the permission.
          return this.hasPermission(permissionName).pipe(
            tap(result => {
              // perform some actions on the result before mapping it to the `result.permission`
            }),
            map(result => result.permission)
          );
        } else {
          // return an observable of true to be processed within subscribe.
          return of(true);
        }
      })
    )
    .subscribe(permission => this.$permissionSub.next(permission));

  return this.$permissionSub.asObservable();
}

If you are not using this.$permissionSub elsewhere, you can remove it from the method above and simply return this.checkCompanySettingForPermission(...) without subscribing to it. You can then call this method in your component like so:

// Example
this.service.checkPermission(addPermission).subscribe((value) => {
   console.log(value)
})

Answer №2

Here is a suggestion for the format you can try.

validateAccess(permission: string): Observable<boolean> {
  this.verifyCompanySettingForAccess(this.settingsName)
    .pipe(
      map(res => res?.Value.toLowerCase() === 'true'
          ? this.checkPermission(permission).pipe(
               map(result => result.granted)
            )
          : of(true)

       ),
      switchMap(observable => observable)
    )
    .subscribe(accessGranted => this.$accessStatus.next(accessGranted));

  return this.$accessStatus.asObservable();
}

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

What is the process for acquiring a comprehensive catalog of Node.js modules?

Currently, I am working on integrating NPM functionality into my Node.js applications. My goal is to be able to analyze the node modules available on my system. When referring to a "module" in this context, it could either be an identifier like "fd" or a f ...

Error in Angular Google Maps Component: Unable to access the 'nativeElement' property as it is undefined

I am currently working on creating an autofill input for AGM. Everything seems to be going smoothly, but I encountered an error when trying to integrate the component (app-agm-input) into my app.component.html: https://i.stack.imgur.com/mDtSA.png Here is ...

Preventing responsive elements from loading with HTML scripts

Currently, I am utilizing the Gumby framework which can be found here. Everything appears to be running smoothly. My goal is to incorporate a mobile navigation list where the links are grouped under a single button, as outlined here. Initially, this funct ...

Encountered an issue with running tests in vscode-test - runTests function throwing

Setting up tests for my vscode extension for the first time and encountering an issue. I copied and pasted the example from code.visualstudio's /working-with-extensions/testing-extension. However, I'm facing an error when trying to call runTest ...

What steps can be taken in Next.js to display a 404 page when data is not retrieved from the Wordpress admin?

I am working with JSON data that looks like this: [ { "taxonomy_slug": "product_cat", "taxonomy_name": "Categories", "frontend_slug": "product-category" }, { ...

Alert: Next.js 13 console error detected

Currently, I am utilizing Next js 13 for the development of a website. However, I have encountered this warning in the console: The resource http://localhost:3000/_next/static/chunks/polyfills.js was preloaded using link preload but not used within a few s ...

What is the best way to connect my data with my Backbone Views?

I have successfully set up my views to show test data, and now I want to implement asynchronous data loading to fetch real information. However, I'm a bit confused on the best method to achieve this. Should I manually create AJAX calls? Or maybe utili ...

Show the "Splash" picture, then switch to a newly uploaded image and show it for a set amount of time

I am in the process of developing an HTML/JavaScript page that will showcase a splash image (splash.jpg) until it gets replaced by another image file called latest.jpg. Once this latest.jpg is displayed, I want it to remain on the screen for 90 seconds bef ...

Comparison: Chrome extension - utilizing default pop-up vs injecting a div directly into the page

I find myself perplexed by the common practices used in popular Chrome extensions. I am currently working on creating my own Chrome extension and after completing a basic tutorial, I have set up a default popup page that appears when clicking the extensi ...

Updating the Background Image Based on Text Input in JavaScript

Struggling to utilize the text entered into a text input field as a background image URL. Ensuring it is valid is key. This snippet displays what has been attempted so far... CSS: body { margin: 0px; padding: 0px; border: 0px; } .bgimg { backgr ...

UI5 Tooling generated an error stating that "sap is not defined" after a self-contained build

Having successfully developed an application using SAPUI5 1.108, I encountered a setback when attempting to deploy it to a system running SAPUI5 version 1.71. The older version lacks certain features, causing the application to fail. In order to address th ...

Is there a way to prevent my timer from resetting whenever I refresh the page?

Hey everyone, I'm new to coding and I could really use some help here. I have this code for a timer but I'm struggling to make it work properly even after refreshing the page. My goal is to keep the timer running smoothly, but I'm not sure w ...

When using the HTML5 draw img feature, only the top 1/4 of the image will be

I am having trouble loading a full image into canvas. Currently, it only displays the top 1/4 of the image regardless of which one I use. Any help would be greatly appreciated. Here is the code snippet in question: var canvas = document.getElementById(&ap ...

What could be causing my LESS files not to compile properly in grunt?

I've successfully installed npm and ran npm init. Additionally, I've installed the following packages using npm: grunt grunt-contrib-less grunt-contrib-watch jit-grunt --save-dev My Gruntfile.js configuration looks like this: module.exports = f ...

Guidelines on dispatching events from Node.js/Express to Angular

I am in the process of a lengthy transaction and I want to keep my client informed about its progress. On the frontend, I am using Angular 4 and on the backend, it's nodeJS/Express. The client triggers the transaction through an HTTP Post request. An ...

Having trouble with ejs.filters?

I'm having trouble grasping ejs filters and getting them to work correctly: Server.js var ejs = require('ejs'); ejs.filters.example = function() { //placeholder for example }; Routes.js app.get('/home', function(req, res) { ...

Double submission issue with Angular form (multiple ajax requests)

My controller seems to be causing a form submission issue in AngularJS where the form is being submitted twice via a get request. Upon checking my database and the console network tab, I noticed that two submissions are logged, with the first submission sh ...

Switching to Next.js

In my Next JS application, I have a div that dynamically displays the currency and price of a product when a user visits a product page. <div className="flex"> <Image src={EuroCurrency} alt="Euro Sign} /> <h1 className=" ...

Error encountered while attempting to save a Mongoose post on Heroku, although it is successful

My aim is to post to my MongoDB Atlas database using node, express, mongoose, and Heroku. While a Postman POST request with Raw JSON body: { "title": "heroku post", "description": "post me plsssss" } works f ...

What is the best way to incorporate async and await into my functions within a Node.js environment?

I attempted to implement asynchronous functionality into my code, however, I encountered some difficulties. What steps should I take next? Below are the functions in question: 1. router.post('/urls', (req, response) => { count = 2; webUrl ...