关于 Angular:Angular2 可观察共享不起作用

Angular2 observable share is not working

Angular2 Observable 共享不工作,重复的 http 调用正在进行

BuildingService.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Injectable()
export class BuildingService {

constructor(private http: Http){      
  }

buildings$: Observable<Building[]>;
this.buildings: Building[];

getData() : Observable<Building[]>{
     this.buildings$ = this.http.get('http://localhost:8080/buildings').share().map(this.extractData);
     this.buildings$.subscribe(buildings => this.buildings = buildings);
     return this.buildings$;
  }

 private extractData(res: Response) {
    let body = res.json();
    return body;
}

}

component1.ts

1
2
3
4
5
6
7
export class component1 {
constructor( private  buildingService: BuildingService) {}

this.subscription = this.buildingService.getData()
            .subscribe(buildings => console.log(buildings),
            error =>  this.errorMessage = error);
}

component2.ts

1
2
3
4
5
6
7
export class component2 {
constructor( private  buildingService: BuildingService) {}

this.subscription = this.buildingService.getData()
            .subscribe(buildings => console.log(buildings),
            error =>  this.errorMessage = error);
}

share 不工作,多个 http 调用正在进行。即使我尝试了此链接中的代码

但没用。

有人可以告诉我如何避免使用 Angular Observable 进行重复的 http 调用吗?


我认为这只是对 share() 作用的误解。

当你调用 this.buildings$.subscribe(...) 时,它会生成一个 ConnectableObservable,这要归功于 share() 运算符,它后面紧跟 connect().

如果您在 HTTP 请求挂起时进行另一个订阅,它只会将另一个观察者添加到 ConnectableObservable 并且当响应准备好时,它将被发送到两个观察者。但是,如果您让 this.buildings$ 完成,然后再次订阅,它将发出另一个 HTTP 请求,因为 ConnectableObservable 未连接到其源。

你想要的是 .publishReplay(1).refCount() (或自 RxJS 5.4.0 以来的 shareReplay(1) ),它重放从源发出的最后一个项目。很可能您还想附加 take(1) 以正确完成链。


您正在使用此处的每个 .getData()-调用创建一个新流:

1
this.buildings$ = this.http.get('http://localhost:8080/buildings').share().map(this.extractData);

如果你想在组件之间"共享"数据并防止多次调用,你很可能必须使用 rxjs 的重播功能,例如,你可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Injectable()
export class BuildingService {

constructor(private http: Http){}

buildings$: Observable<Building[]>;
this.buildings: Building[];

getData(fetchNew: boolean = false) : Observable<Building[]>{
     if (fetchNew || !this.buildings$) {
         this.buildings$ = this.http.get('http://localhost:8080/buildings')
             .map(this.extractData)
             .publishReplay(1)
             .refCount();
         this.buildings$.subscribe(buildings => this.buildings = buildings);
     }
     return this.buildings$;
  }

  private extractData(res: Response) {
    let body = res.json();
    return body;
  }
}

publishReplay(1) 将重新发送("replay") 上次发送的数据给未来的订阅者,因此不会进行新的调用。


您在服务和组件中都订阅了 observable。试试这个作为你服务中的 getData 方法:

1
2
3
4
getData() : Observable<Building[]>{
 return this.http.get('http://localhost:8080/buildings')
    .map(this.extractData);
}