繁体   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