簡體   English   中英

每次通過注入組件實例化角服務

[英]Angular service instantiated every time by injection to component

我實現了一項服務,該服務應一次獲取數據並緩存結果。 該服務位於根級別。 每當我將此服務注入組件的構造函數中並訂閱該方法時,該服務都會發出新的http請求。

我已經嘗試過將請求代碼從構造函數中移到方法中。

@Injectable({
  providedIn: 'root'
})
export class SessionService {
  private api = Configuration.api + 'session/';
  private readonly session$: Observable<Session>;

  constructor(private http: HttpClient) {
    this.session$ = this.http
      .get<any>(`${this.api}current`, {withCredentials: true})
      .pipe(
        timeout(Configuration.timeout),
        retry(Configuration.retry),
        map(data => {
            return data.session as Session;
          }
        ),
        catchError(ErrorService.handleError)
      );
  }

  getCurrentSession(): Observable<Session> {
    return this.session$;
  }
}

export class Component implements OnInit, AfterContentInit {
session = Session.empty();

  constructor(
    private _s: SessionService) {
    this._s.getCurrentSession().subscribe(session => this.session = session);
  }
}

目的是執行一次請求並將結果緩存在變量中。

可觀察對象是流的定義,它們在每個訂閱上執行,因此每次您只訂閱導致其執行的http請求時。 為了解決這個問題,您需要訂閱構造函數並將結果存儲在將處理緩存的主題中:

export class SessionService {
  private api = Configuration.api + 'session/';

  private session$ = new ReplaySubject<Session>(1);

  constructor(private http: HttpClient) {
    this.loadSession();
  }

  loadSession() {
    this.http
      .get<any>(`${this.api}current`, {withCredentials: true})
      .pipe(
        timeout(Configuration.timeout),
        retry(Configuration.retry),
        map(data => {
            return data.session as Session;
          }
        ),
        catchError(ErrorService.handleError)
      ).subscribe(this.session$);
  }

  getCurrentSession(): Observable<Session> {
    return this.session$.asObservable();
  }
}

盡管您也可以這樣做:

this.session$ = this.http
  .get<any>(`${this.api}current`, {withCredentials: true})
  .pipe(
    timeout(Configuration.timeout),
    retry(Configuration.retry),
    map(data => {
        return data.session as Session;
      }
    ),
    catchError(ErrorService.handleError),
    shareReplay(1)
  );

shareReplay運算符或多或少執行完全相同的操作。 我之所以喜歡我建議的原始方法,是因為它提供了一種更簡便的方法,可以在需要時強制重新加載數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM