-->

How to get rid from redundant request in Angular 6

2020-07-27 03:01发布

问题:

I have 3 independent places in my code which call VerificationService method getOrganizationView().

getOrganizationView(): Observable<any> {
  return this.httpClient.http.post(...)
}

First place is principal service:

@Injectable()
export class Principal {
   constructor(private verificationService: VerificationService) {}
   identity(force?: boolean): Promise<any> {
      return this.verificationService.getOrganizationView().toPromise().then((response ) => {
          ...
      })
   }
}

And one more service called LinkAccessService which do the same Principal that's not the point

And one more place is component:

export class VerificationComponent implements OnInit {
   constructor(private verificationService: VerificationService) {
   }

   ngOnInit() {
     this.verificationService.getOrganizationView()
       .subscribe((data: VerificationView) => {
         ...
     });
  }
}

And at loading app moment I had 3 calls instead single request, but these entities absolutely independent and I can't share data like between components directive and so on...

How traditionally in Angular 2+ resolve issue like this? I'm not mean distinct code for answer, I mean idea.

回答1:

The simplest way to cache your data is using shareReplay rxjs operator:

import { shareReplay } from 'rxjs/operators';

@Injectable()
export class VerificationService {
  organizationViewCache$: Observable<any>;

  getOrganizationView() {
    if (!this.organizationViewCache$) {
      this.organizationViewCache$ = this.http.get(...).pipe(shareReplay(1));
    }

    return this.organizationViewCache$;
  }
}

See also:

  • Advanced caching with RxJS


回答2:

You could build a service that retrieves and caches the data. Any component that injects the service can then access that cached data without another request to the server.

export class ProductService {
    private productsUrl = 'api/products';
    products: IProduct[];

    getProducts(): Observable<IProduct> {
        // Returns the cached list if it exists.
        if (this.products) {
            return of(this.products);
        }
        return this.http.get<IProduct[]>(this.productsUrl)
                        .pipe(
                            tap(data => this.products = data),
                            catchError(this.handleError)
                        );
    }
}

There are several other answers, including using RxJS ReplaySubject here: What is the correct way to share the result of an Angular Http network call in RxJs 5?



回答3:

I'm not 100% sure how your app is set up. But I would look into using an Event Emitter if I were you. You can have it emit an event, that your different components will listen to. Whichever component is supposed to make the call will make it appropriately and the others should not.