Angular method that returns an Observable with a combination of pipe, switchMap, and forkJoin

Can someone help me modify this code so that it returns an Observable<ApiResponse>? I'm unsure if my current approach is correct.

private doRequestProducts() {

        const sequence$ = this.http.post<ApiResponse>(this.baseUrlOverview, {} { observe: 'response' }).pipe(
        switchMap(res => {
          if (res.status !== 200) {
            throw new Error('Value expected!');
          }
          const productResponse: productOverviewResponse = {... res.body.data};
          const responses: Observable<ApiResponse>[] = [];
          productResponse.Products.forEach((item, index) => {
            const response: Observable<ApiResponse> = this.http.post<ApiResponse>(this.baseUrlDetail, {
              productID: item.productId,
            });
            responses.push(response);
          });

          return forkJoin(responses).pipe(
              map(d => {
                const items: product[]  = [];
                d.forEach((api) => {
                  if (api.status === 'ok') {
                    const invResp: product = {... api.data};
                    items.push(invResp);
                  }
                });
              })
            );
          }
        ));
      }

Answer №1

You neglected to include the return statement in the doRequestProducts function. Overall, the approach seems solid but could benefit from some minor tweaks. I recommend using map instead of the foreach+push method.

Here's a suggestion:

private doRequestProducts(): Observable<Data[]> {
    return this.http.post<ApiResponse>(this.baseUrlOverview, { observe: 'response' }).pipe(
        tap(res => {
            if (res.status !== 200) {
                throw new Error('Value expected!');
            }
        }),
        map(res => res.body.data.Products),
        switchMap(products => {
            const productResponses: Observable<ApiResponse>[] = products.map(product => this.http.post<ApiResponse>(this.baseUrlDetail, { productID: product.productId }));
            return forkJoin(productResponses);
        }),
        map((responses: ApiResponse[]) => responses.filter(response => response.status === 'ok').map(response => response.data)),
    );
}

Additional details:

  • The function will not return an Observable<ApiResponse>. Instead, it will return an Observable containing an Array with the data Object type. In my example, I referred to this type as Data.
  • It appears that you have a generic API response that requires mapping each time it is used. You may want to consider creating a mapper from ApiResponse to any specific Type for improved type safety.

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

Error encountered: Angular2 is unable to locate the traceur module after integrating the hltv-api npm

Following a direct npm install of the hltv-api package, I attempted to import it into my component.ts file with the following code: import { getNews, getResults } from 'hltv-api'; I then configured my systemjs.config.js fi ...

Utilize dual providers with distinct generic typings in Angular Jasmine testing for a single class

I am currently working on creating two separate mock providers and spys for classes that are injected into my component. Even though the dependencies involve the same class, they use different typings through the use of generics. constructor( private reado ...

Classes in Typescript can implement interfaces to streamline the functionality

Recently, I've been working on creating my custom class called AxiosError and I can't help but feel like the code is a bit repetitive. //types.ts export interface IAxiosRequest{} export interface IAxiosResponse{} export interface IAxios ...

Tips for automatically scrolling to the top of a Material2 Angular2 dialog box

I'm currently utilizing the Dialog box feature from https://material.angular.io. Specifically, I am facing an issue where when I try to position the dialog box using: config = {'width':'200px', 'height':'400px' ...

Strategies for implementing searchbar filtering in Ionic3 and Angular5 data manipulation

I'm having trouble displaying product names on my search.html page based on the search bar input. I've tried using the Ionic searchbar component but it's not working. Can anyone help me with this issue? If there's an alternative solutio ...

Deliberately choosing not to fulfill the Bluebird Promise

Here is a piece of code that needs to call a callback which may return a promise. The goal is to resolve the promise and log an error if it fails, without the caller knowing about it or waiting for the promise to fulfill. However, not returning the promise ...

There appears to be an issue with the indexes of the PointCloud

After setting up a point cloud and attempting to change vertex colors upon clicking a point, I encountered some issues. Despite working out the vertex colors and necessary indices, the colors do not change as expected. The index values also seem confusing ...

Create an Observable by combining two interconnected sources

I need to combine values from two different Observables into one Observable. The solution is using the zip operator, but my situation is a bit more complex. I have an id for A. A {id, name, idOfRelatedB} //first observable B {...} // second So, in order ...

The superclass defines the type of the subclass

There is an abstract typescript class like this: abstract class Abstract { constructor (public parent?: Abstract) { } } Then, two subclasses are defined as follows: class Sub1 extends Abstract { } class Sub2 extends Abstract { } The issue aris ...

Obtaining user roles from server without using JWT tokens

My main objective is to provide user roles from the backend. For instance, if a user wishes to access resources in my backend, they can log in using Google credentials. The Angular app retrieves the access token from the Google authorization server and s ...

All components have been brought in, however, Nest is struggling to resolve the dependencies required by the stripePaymentService

I'm currently in the process of integrating the Stripe payment gateway with NestJS. I've encountered an error message stating "Nest can't resolve dependencies of the stripePaymentService". Even though I'm familiar with this type of erro ...

Is it possible to utilize the Lit javascript module from a CDN without including the bundled Lit dependencies?

Is there a method to distribute a Lit element created from TypeScript without including the Lit dependencies in the web component bundle? For instance, we can serve the rollup bundle as mentioned here from Unpkg. However, I am curious if it's possibl ...

Make sure that every component in create-react-app includes an import for react so that it can be properly

Currently, I am working on a TypeScript project based on create-react-app which serves as the foundation for a React component that I plan to release as a standalone package. However, when using this package externally, I need to ensure that import React ...

Angular Form Template Unidirectional Data Binding Example

I'm facing a challenge with one-way binding to a default value in my HTML form. Within my component, I have a Connection string that is initially set from local storage: export class AuthAdminComponent implements OnInit { public authenticated = f ...

Unlock the Full Potential of TypeScript: Seamless Export of Classes and Functions

In my AngularJS project, I have a separate JavaScript file where I declare prototype functions. Here's an example: function lastConv(){ this.item1="2" this.message="hello" ...... } lastConv.prototype.setupfromThread(data) { this.currentBox = dat ...

"Efficiently Distributing HTTP Requests Among Simultaneous Observers using RxJS

Currently, I am working on a feature in my Angular application that requires handling multiple concurrent fetches for the same data with only one HTTP request being made. This request should be shared among all the subscribers who are requesting the data s ...

What could be the reason for the crash caused by ngModel?

The usage of [(ngModel)] within a *ngFor-Loop is causing an endless loop and crashing the browser. This is how my HTML looks: <div class="container"> <div class="row" *ngFor="let item of controlSystemTargetViewModel.values; let index = i ...

The Cordova InAppBrowser plugin has not been properly set up

After running cordova plugin list, I noticed that the InAppBrowser plugin is listed. However, when I try to run my code on an android device, I receive this message in the console via Chrome Remote Debugger: Native: InAppBrowser is not installed or you ar ...

What is the best method in Angular to reset form errors after submission?

Manually setting error validation in my form using setErrors is not providing clear errors upon submission. I do not want to reset all control errors to null, as this may cancel out other existing errors on the control. After setting the error once, I ne ...

Can the component life cycle be halted with an interrupt option?

Currently, I am focusing on integrating RBAC into my angular application. My goal is to halt the component lifecycle and prevent the rendering of the component template (along with any child components/templates) if the user does not have the necessary ent ...