使用从 API 服务器检索的服务在组件之间共享数据

Sharing data between components using service retrieved from an API server

我正在从我在多个组件上使用的 API 服务器获取数据。但是,如果我尝试使用服务共享数据,则组件会在检索数据之前进行处理。

我可以检索每个组件中的数据,但是用户必须在加载每个页面(组件)之前等待数据被检索。数据不会改变,所以我希望能够 http.get() 一次数据并操纵各个组件中的视图。

我也可以将数据从父级传递给子级 - 但是,由于它们是多个页面,因此无法通过路由器和@Input() 共享数据。

现在,我正在尝试使用共享服务。该服务最终 returns 数据,但页面尝试在检索数据之前加载,这意味着没有显示任何数据。

app.component.html

<div class="router-body">
      <router-outlet ></router-outlet>
    </div>

api.service

createData(url): Observable<any> {
    this.http.get<Person[]>(url)
        .subscribe(people => {
          console.log("in createData()");
          this.people = people;

        });
        return of(this.people);
  }

people.component

  ngOnInit() {
    this.apiService.createData(this.apiService.personURL)
    .subscribe( people => { 
        console.log("data within people.component");
        console.log(this.people);
        this.people = people });
  }

people.component this.people 得到 'undefined' api.service returns 最终数据,但人员页面从未显示它。

我需要一个方法 1 - 一次拉取数据 2 - 在人员页面(或其他页面)上显示数据

我建议使用一个主题来分享这种数据:

首先在您的数据服务中创建一个 Person[] 类型的主题:

ppl$: Subject<Person[]> = new Subject();

然后定义一个getter:

getPplObs(): Observable<Person[]> {
  return this.ppl$.asObservable();
}

当您在服务上设置数据时,将值传递给主题:

createData(url): Observable<any> {
    this.http.get<Person[]>(url)
        .subscribe(people => {
          console.log("in createData()");
          this.people = people;
          this.ppl$.next(people);
        });
  }

现在你只需要在你的组件 ngOnInit 中订阅那个 Observable:

ngOnInit() {
  this.apiService.getPplObs().pipe(takeUntil(this.unsubscribe$)).subscribe(ppl => this.people = ppls);
}

为了在组件销毁时正确取消订阅,我使用了 takeUntil。创建主题

unsubscribe$: Subject<boolean> = new Subject();

然后在 ngOnDestroy 生命周期中:

ngOnDestroy() {
  this.unsubscribe$.next(true);
  this.unsubscribe$.complete();
}

问候

对于以下内容,您总是先 returning people,因为这是异步的。

createData(url): Observable<any> {
  this.http.get<Person[]>(url)
    .subscribe(people => {
        // takes x time to complete
        console.log("in createData()");
        this.people = people;
     });
     // this line is executed while waiting for above response
     return of(this.people);
}

我总是 return 一个 http 请求的可观察对象,或者 people 的一个可观察对象。可以使用tap先将数据存入变量:

import { tap } from 'rxjs/operators';

// ...

people = <Person[]>[];

createData(url): Observable<Person[]> {
  if (this.people.length) {
    return of(this.people)
  }
  return this.http.get<Person[]>(url)
    .pipe(
      tap(people => this.people = people)
    )
}

并记得在您的组件中取消订阅。