寻找一种方法,使服务在必要时将最新数据提供给订阅组件。例如:Component3将更改写入API> Component1和Component2必须获取最新数据。
目前,两个组件都订阅了服务返回的observable,如果两个API请求都被渲染,则会导致2个API请求。这感觉不对。根据我的理解,这些组件应该由数据提供,而不是自己请求。需要明确的是:此服务返回的数据始终在Component1中使用,而Component2可选地呈现。
这里有一些片段和对我到目前为止所做的一些描述:
服务通过HTTP从API获取数据。 Component1 和 Component2 订阅服务返回的observable:
import { Injectable } from "@angular/core";
import { Http } from "@angular/http";
import 'rxjs/add/operator/map';
@Injectable()
export class GroupService{
constructor(private _http: Http){}
getGroups(){
return this._http.get('/assets/groups.json')
.map((res) => {
return res.json();
});
}
}
Component1 和 Component2 在功能方面基本相同。这是其中之一:
import { Component } from '@angular/core';
import { router } from '../../app.router';
import { GroupService } from '../../services/group.service';
import { Group } from '../../interfaces/group.interface';
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss'],
})
export class SidebarComponent
{
router;
groups: Group[];
constructor(private _groupService: GroupService){
this.router = router;
this.getGroups();
}
getGroups(){
this._groupService.getGroups()
.subscribe((groups) => {
this.groups = groups;
});
}
}
答案 0 :(得分:4)
与seidme的方法稍有不同,我个人更喜欢:
在GroupService
中设置数据流,并在组件中使用该数据流。
服务:
import { Injectable } from "@angular/core";
import { Http } from "@angular/http";
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
@Injectable()
export class GroupService {
private groupSource = new BehaviorSubject<any>({});
public group$: Observable = this.groupSource.asObservable();
constructor(private _http: Http) {}
getGroups() {
this._http.get('/assets/groups.json')
.map((res) => {
return res.json();
})
.subscribe((groups) => this.groupSource.next(groups));
}
}
然后在您的组件中,执行此操作:
import { Component, OnInit } from '@angular/core';
import { router } from '../../app.router';
import { GroupService } from '../../services/group.service';
import { Group } from '../../interfaces/group.interface';
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss'],
})
export class SidebarComponent implements OnInit {
router;
groups: Observable;
constructor(private _groupService: GroupService){
this.router = router;
}
ngOnInit {
this.groups = this._groupService.group$;
}
}
然后在您的模板中,使用async
管道:{{ groups | async }}
。它将负责为您订阅(和处置)observable。
现在,只要您从任何组件中调用GroupService.getGroups()
,其他所有组件都会自动更新。
此外,使用OnInit
稍微比在构造函数中执行操作更可取,请参阅Difference between Constructor and ngOnInit。
答案 1 :(得分:2)
使用BehaviorSubject as a delegate可能是您用例最方便的选项。在服务中注册BehaviorSubject
,并在任何这些组件请求新数据时需要更新的所有组件中订阅它。
这就是服务的样子:
@Injectable()
export class GroupService {
groupsSource: BehaviorSubject<any> = new BehaviorSubject(null);
constructor(private _http: Http) { }
getGroups(): void {
this._http.get('/assets/groups.json')
.map((res) => res.json())
.subscribe((groups) => this.groupsSource.next(groups)); // Update all components subscribed to the BehaviorSubjet
}
}
组件1,请求新数据:
export class Component1 implements OnInit {
groups: any;
constructor(private _groupService: GroupService) { }
ngOnInit() {
this._groupService.groupsSource.subscribe((groups) => {
this.groups = groups;
});
this._groupService.getGroups();
}
}
组件2,自动更新:
export class Component2 implements OnInit {
groups: any;
constructor(private _groupService: GroupService) { }
ngOnInit() {
this._groupService.groupsSource.subscribe((groups) => {
this.groups = groups;
});
}
}
使用BehaviorSubject
,您可以获得最新的价值而无需订阅它:
export class Component3 implements OnInit{
groups: any;
constructor(private _groupService: GroupService) { }
ngOnInit() {
this.groups = this._groupService.groupsSource.getValue();
}
}