Angular / rxjs / Subject / BehaviorSubject跨多个组件共享http服务数据

时间:2017-09-26 14:50:57

标签: angular rxjs

跟进Share data between components using a service in Angular2的问题以及我得到的回复。

我正在尝试共享服务提供商通过GET检索的数据。 组件结构如下,主要路由指向CustomerPortalDashboardComponent和DocumentsComponent

<CustomerPortalBaseComponent>
 <router-outlet>
  <CustomerPortalDashboardComponent/> 
  <DocumentsComponent/>
 <router-outlet>
</CustomerPortalBaseComponent>

CustomerPortalBaseComponent进行调用以获取用户信息:

ngOnInit() {
this.customerPortalUserService.getUserInfo()
  .subscribe(
    (event: HttpEvent<any>) => {
      switch (event.type) {
        case HttpEventType.Sent:
          break;
        case HttpEventType.Response:
          this.handleUserData(event.body)

      }
    },
    (err: HttpErrorResponse) => {
      if (err.error instanceof Error) {
        console.log("Client-side error occured.");
      } else {           
        console.log("Server-side error occured.");
      }
    }
  )
}
 handleUserData(data: any){
  this.userData = data;
}

CustomerPortalUserService

getUserInfo(){
interface ItemsResponse {
  results: string[];
}
return  this.http.get<ItemsResponse>(this.userUrl,  {
  observe: 'response',
  headers: new HttpHeaders().set(),
})
}

在CustomerPortalDashboardComponent和DocumentsComponent中获取userData并确保在其他组件尝试获取之前已检索到数据的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

要使其发挥作用的几点:

  1. 要确保在到达路线之前加载数据,您可以使用resolver。解析器将链接到您的路径路径,并且将是在解析路由之前执行Http请求的函数。
  2. 您需要在拨打电话后将数据存储在商店中。这可以通过@Ngrx等外部商店来完成,但最基本的例子是在服务中使用变量(使用getter / setter更好):
  3. 示例服务:

    _equipmentDetails: any  // Should be private in use-case
    
    ...
    
    getEquipmentDetail(clientId, modemId): Observable<any> {
      const url = 'myOwnUrl';
    
      return this.Http
        .get(url)
        .map(result => {
          if (result) {
            // Notice how I set the value from the Http call.
            return this._equipmentDetails = result.json();
          }
        })
        .catch(this.handleError);
    }
    

    然后,您可以通过依赖注入从组件中获取属性值。

      constructor(
        ...
        private equipmentService: ServiceClass,
      ) {
        this.equipmentService._equipmentDetails;
      }
    

答案 1 :(得分:1)

使用共享服务解决了这个问题。在我使用Subject而不是BehaviorSubject的共享服务中,我之前是这样做的。主题不缓存数据,所以我认为我的设计模式不起作用。当改为BehaviorSubject时,一切都很完美。

CustomerPortalBaseComponent对将在此应用程序模块中共享的数据进行所有HTTP调用。然后,它将消息发送到共享服务,其他组件(路由的主要组件)订阅该服务。 EX:

CustomerPortalBaseComponent

this.applicationsMessagingService.sendMessage(data)

ApplicationsMessagingService:

Injectable()
export class ApplicationsMessagingService {

  private subject = new BehaviorSubject<any>(null);

  sendMessage(message: {}) {
   this.subject.next(message);
  }

  clearMessage() {
   this.subject.next(null);
 }

  getMessage(): Observable<any> {
   return this.subject.asObservable();
  }

}

CustomerPortalDashboardComponent

ngOnInit() {
this.subscription = this.applicationsMessagingService.getMessage().subscribe(message => {
  this.message = message;
  this.handleApplicationData(this.message);
});


handleApplicationData(data: any){
  if (data){
   this.applicationData = data;
 }
}

然后将applicationData传递给子组件并通过@input

接收