What is the process for sending an http request using the information gathered from a previous http request?

One of the properties in my Issue object is an array of Tool objects, with both Issues and Tools stored in separate tables in my database.

In my issues-log.component, I am successfully dispatching an action to search for matching issues based on a query.

Now, my goal is to retrieve the list of tools associated with each issue by passing the issue id to my tools service. To achieve this, I created another effect that listens for the ISSUE.SEARCH.COMPLETE action. However, looping through the array of issues in my tools service to call the API for each issue id feels inefficient. It slows down the loading time for large lists of issues and limits the re-usability of my tools service.

I don't want to wait for all the issues to load before fetching the associated tools. Is there a way to optimize my code so that I can start adding the tools as the list of issues is being constructed within the issuesSearch$ effect?

Component:

@Component({
selector: issue-log,
template: `
  <issue-search (search)="search($event)></issue-search>
  <issue-list [issues]=$issues | async></issue-list>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class IssueLogComponent {
  issues$: Observable<Issue[]>;

  constructor(private store: Store<fromRoot.State>) {
    this.issues$ = store.select(fromRoot.getIssueSearchResults);
  }

  search(query) {
    this.store.dispatch(new issue.IssueSearch(query));
  }
}

Effect:

@Effect() issueSearch$: Observable<Action> = this.actions$
  .ofType(issue.ISSUE_SEARCH)
  .debounceTime(300)
  .map(toPayload)
  .switchMap(query => {
    if (query === '') {
      return empty();
    }
    const nextSearch$ = this.actions$.ofType(issue.ISSUE_SEARCH).skip(1);
    return this.issueService.getIssuesFromQuery(query) //calls API service
      .takeUntil(nextSearch$)
      .mergeMap((res: Issue[]) => {
        // How do I make another API call here, passing data from each element of res array?
        return Observable.from([
          new issue.IssueSearchComplete(res)
        ])
      })
      .catch(() => of(new issue.IssueSearchComplete([])));
});

I also attempted calling my tools service from within my issues service, but it didn't feel like the right solution.

Answer №1

If you require immediate access to the results of your issues before making any other asynchronous requests based on that data, consider utilizing an RxJS Subject.

You can observe the subject for issues and subscribe to the final calls' observable as well.

Here is how it breaks down:

  1. Fetch issues
  2. Pass the issues to another observable stream for immediate access
  3. Use the issues to make additional async calls
  4. Return the result of the final calls, which can also be subscribed to

This approach requires subscribing to two separate observable streams.

Here's a simplified example:

@Injectable()
export class FooService {
    issuesSubject: BehaviorSubject<Issue[]> = new BehaviorSubject([]);

    get issues$(): Observable<Issue[]> {
        return this.issuesSubject.asObservable();
    }

    getIssuesAndMakeOtherAsyncCalls(): Observable<any> {
       return this.issueService
                  .getIssuesFromQuery(query)
                  .flatMap((issues: Issue[]) => {
                      // Add issues to the stream here
                      this.issuesSubject.next(issues);

                      // Make other HTTP calls using the issues
                      return this.makeSomeOtherCallsUsingIssues(issues);
                  })
    }
}

In your component:

@Component({})
export class FooComponent implements OnInit {
    ngOnInit() {
        this.issueService.getIssuesAndMakeOtherAsyncCalls().subscribe(res => {
            // Result from the service call will be available in `res`
        });

        this.issueService.issues$.subscribe((issues: Issue[]) => {
            // Receive the issues when `this.issuesSubject.next(issues)` is triggered in the service
        });
    }
}

Does this solution meet your requirements?

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

The entry for package "ts-retry" could not be resolved due to possible errors in the main/module/exports specified in its package.json file

I encountered an error while attempting to run my React application using Vite. The issue arises from a package I am utilizing from a private npm registry (@ats/graphql), which has a dependency on the package ts-retry. Any assistance in resolving this pro ...

The current state of this scenario is not clearly defined within the parent class

Here is the scenario that caught my attention: abstract class Base { public _obj = { name: 'Test' } print1() { console.log(this._obj) } print2() { console.log(this) } } class Child extends Base { print2( ...

Choose a duplicate of an element from an array using JavaScript

I have a function that receives an array of items as a parameter. Within this function, I need to locate a specific item and update one of its properties. const defaultGroup = find(groupedCustomFields, group => group.name === DEFAULT_GROUP); //[find][1 ...

Subscribe again to an observable from a header module

Within my Angular service, I have an Observable that showcases a countdown timer for a user's e-commerce order when they reach a specific route after adding items to their cart. Although it functions correctly the first time an order is initiated, if ...

Updating a value from a provider in Angular: A step-by-step guide

I have an AppModule provider that provides a specific class. Is it possible to change the provided value dynamically at runtime? {provide: MatDatepickerIntl, useClass: SomeClass} How can I switch from using SomeClass to AnotherClass on the fly (for examp ...

When performing an arithmetic operation, the right operand must be a data type of 'any', 'number', 'bigint', or an enumeration type

My JavaScript code needs to be converted to TypeScript for proper functionality. categoryAxis.renderer.labels.template.adapter.add("dy", function(dy, target) { if (target.dataItem && target.dataItem.index % 2 === 0) { return dy + 25; } ...

Linking Ionic Apps to Different Subfolders

In order to redirect users to my ionic app instead of my website, I have successfully implemented universal links. However, the issue now is that all URLs within my domain (e.g. ) are being opened by the app. What I actually want is for only URLs from a sp ...

The collaboration of React hooks, typescript, mongoose, express, and socket.io in perfect harmony

I am currently working on setting up a frontend React app to communicate with a NodeJS Express API using socket.io import React, { useEffect, useState } from "react"; import io from "socket.io-client"; const socket = io("http://lo ...

The error message states that the property 'id' is not found on the 'User' type when using Passport and Typescript

When I try to access req.user.id while using PassportJS in Express with Typescript, I encounter the following error: Property 'id' does not exist on type 'User'.ts(2339) Upon logging req.user to the console, the id property is clearly ...

Following the migration to Typescript, the React component is having trouble locating the redux store props and actions

Here is the structure of my app: export default class App extends Component { render() { return ( <Provider store={store}> <Router> <Header/> ...

Having trouble passing mock data into a functional component and attempting to iterate over an array to display attributes in spans. However, encountering type errors that prevent access to the mock data

I am currently working on a React/TypeScript Component where I need to import mock data in order to iterate over it and display a specific attribute within a span element. However, I have encountered some challenges. It seems that I am unable to pass the ...

In order to deactivate all buttons generated by ngFor in Angular 8, you can disable every button except for the one that has been

If you want to see the full functionality, please make sure to open it in a full browser window by clicking this link. Once opened, try clicking on the button or image of any list item - it will change its appearance as if it's active. Even if you ref ...

Refreshing a component in Angular/Angular2 using routerLink from the NavBar when already on the current route

When I am on the same route and click again from the navbar, nothing happens. Is there a way to refresh my component directly from the navbar using a method in routerLink? <li [routerLinkActive]="['active']"><a [routerLink]="['/ca ...

The functionality of GetStaticProps with Typescript is only operational when defined as an arrow function, rather than a function

The documentation for GetStaticProps in NextJs explains it as a function declaration. When trying to add types to it, the following code snippet results: export async function getStaticProps(): GetStaticProps { const db = await openDB(); const fa ...

Is there a way to utilize req.query, req.params, or req.* beyond its original scope without the need to store it in a database?

Looking to streamline my code and apply the DRY pattern, I've been working on creating a helper function for my express http methods. The structure of each method is similar, but the req.params format varies between them. Here's how I attempted t ...

Encountered an error while attempting to load http://localhost:9999/auth-service/oauth/token: The response for preflight request returned an unexpected HTTP status code

When attempting to generate an OAuth2 token, I utilized Spring Boot OAuth2 and Angular 5. In Postman and curl, I successfully generated the token by providing the appropriate values. However, when using the same parameters in the Angular POST request, it ...

How can we determine if the mat-datepicker popup was closed due to a date being selected?

Is there a way to detect when the mat-datepicker popup closes after a date is selected? I want to perform certain actions only if the user clicked on a date, not if the popup was closed by using the escape key or backdrop click. I am aware of the @Output( ...

Production is experiencing a hiccup, however, the site is still up and running. There seems to be

Having an error in production that I can't seem to replicate on my local machine. The error message reads: src/controllers/userController.ts(2,29): error TS2307: Cannot find module '../services/UserService' or its corresponding type declarat ...

How can conditional types be implemented with React Select?

I am working on enhancing a wrapper for React-select by adding the capability to select multiple options My onChange prop is defined as: onChange: ( newValue: SingleValue<Option>, actionMeta: ActionMeta<Option>, ) => void Howev ...

Enhanced Autocomplete Feature with Select All Option in MUI

Currently, I am utilizing Material UI (5) and the Autocomplete component with the option for multiselect enabled. In addition, I am implementing the "checkbox" customization as per the MUI documentation. To enhance this further, I am attempting to incorpor ...