如何强制我的函数按顺序调用?

How can I force my functions to call in order?

总结:我有一个图表组件,一个过滤器菜单组件,以及一个过滤和设置 BehaviorSubject 的服务。我希望我的服务最初进行 http 调用以获取数据,我的过滤器菜单将过滤日期传递给服务以过滤数据,最后我的图表组件订阅 BehaviorSubject 以便它可以显示过滤后的数据。

筛选菜单组件:

export class FilterMenuComponent {
startDate: string;
endDate: stirng;

constructor(private service: FilterService) { }

ngOnInit() {
    this.service.setData();
    this.setDates();
}

setDates() {
    //grabs dates from ui
    this.service.filterData(startDate, endDate);
}

过滤服务:

export class FilterService {
filteredDataBS: BehaviorSubject<Data>;
data: Data;

constructor(private _http: HttpClient) { }

setData() {
    //http call to get initial data
    this._http.get().subscribe(data => {
        this.data = data;    
    });
}

filterData(startDate: string, endDate: string) {
    this.data = this.data.filter(xxxxxxxxxxxxxx); 
    this.filteredDataBS.next(data);
}

图表组件:

export class ChartComponent {
data: Data;

constructor(private service: FilterService) { }

ngOnInit() {
    this.service.filteredDataBS.subscribe(data => {
        this.data = data;
    });
}

问题: 由于设置初始数据的 http 调用可能需要相当长的时间,因此 FilterMenuComponent 已经在进行并调用以过滤数据。然后我在调用 .filter on undefined 时出错。我需要 FilterMenuComponent 等待并调用 this.service.filterData(),直到 FilterService 从 http 调用返回其初始数据。

您必须 return 从您的函数中观察到 setData 来检测何时过滤数据。以下是您的操作方法:

setData() {
  // Return an Observable to detect when data has
  // been received
  return new Obervable(observer => {
    //http call to get initial data
    this._http.get().subscribe(data => {
      this.data = data;
      observer.next();
    });
  });
}

然后在您的 FilterMenuComponent 中订阅可观察对象:

ngOnInit() {
  this.service.setData().subscribe(() => {
    this.setDates();
  });
}

下面是一个解决方案

筛选菜单组件:

export class FilterMenuComponent {
startDate: string;
endDate: stirng;

constructor(private service: FilterService) { }

ngOnInit() {
    this.service.setData();
    this.filteredDataBS.subscribe(result =>  this.setDates());
}

setDates() {
    //grabs dates from ui
    this.service.filterData(startDate, endDate);
}

过滤服务:

export class FilterService {
filteredDataBS: BehaviorSubject<Data>;
data: Data;

constructor(private _http: HttpClient) { }

setData() {
    //http call to get initial data
    this._http.get().subscribe(data => {
        this.data = data;    
        this.filteredDataBS.next(data);
    });
}

filterData(startDate: string, endDate: string) {
    this.data = this.data.filter(xxxxxxxxxxxxxx); 
    this.filteredDataBS.next(data);
}

使用filteredDataBS来指示日期数据何时加载,然后通过订阅使用它

下面是一个解决方案

筛选菜单组件:

ngOnInit() {
    this.service.setData();
    this.filteredDataBS.subscribe(result =>  this.setDates());
}

过滤服务:

setData() {
    //http call to get initial data
    this._http.get().subscribe(data => {
        this.data = data;    
        this.filteredDataBS.next(data);
    });
}

使用filteredDataBS来指示日期数据何时加载,然后通过订阅使用它

而不是在 FilterMenuComponentngOnInit 中调用 setDates(),您可以在 _http.get() 回调中调用它:

setData(startDate, endDate) {
  //http call to get initial data
  this._http.get().subscribe(data => {
    this.data = data;
    this.filterData(startDate, endDate);
  });
}

但它需要通过 startDateendDate。您还可以将此变量作为其属性保存在 FilterService class 中。

如果你不想这样做,就像其他用户建议的那样,return 来自 setData() 的有限 Observable。