typescript 如何在 Angular 2 中“链接”两个单独的可观察对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38870195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:44:11  来源:igfitidea点击:

How to "chain" two seperate observables in Angular 2

angulartypescriptobservable

提问by moessi774

I am developing a web application with Angular2 and I have got some problems with getting data from the server.

我正在使用 Angular2 开发 Web 应用程序,但在从服务器获取数据时遇到了一些问题。

 import ...

 @Component({
 ...

 })
 export class EmployeeManagementTableComponent implements OnInit, OnDestroy{

private employees: Employee[];
private departments: SelectItem[] = [];
private selectedDepartment: string;
private columns: any[];
private paramSub: any;
private employeesSub: any;
private departmentSub: any;


constructor(private employeeManagementService: EmployeeManagementService, 
            private route: ActivatedRoute, 
            private router: Router,
            private ccs: ComponentCommunicatorService,
            private logger: Logger) { }

ngOnInit(){

    this.columns = [
     ...
    ];

    //ccs is just a service for storing/getting app wide infomation

    this.selectedDepartment = this.ccs.getSelectedDepartment();
    this.getDepartments();
    this.getEmployees(this.selectedDepartment);

    ...
}

ngOnDestroy(){
    /*this.employeesSub.unsubscribe();
    this.departmentDub.unsubscribe();*/
}

getDepartments(){

    this.departments.push({label: 'Alle', value: 'all'});

    this.departmentSub = this.employeeManagementService.getDepartments().subscribe(
          data =>  {data.forEach((item, index) => {
                        this.departments.push({label: item, value: index.toString()});
                    });    
                   },
          err => this.logger.error(err),
          () => {this.logger.log('done loading');
                 this.departmentSub.unsubscribe()}
    );
}
getEmployees(department: any){

this.employeesSub = this.employeeManagementService.getEmployees(department).subscribe(
          data => {this.employees = data},
          err => this.logger.error(err),
          () => {this.logger.log('done loading');
                 this.employeesSub.unsubscribe()}
    );
}

As you see when the component gets initalized it calls two Methods for getting data. The methods get observables from my service and subscribe to them.
The problem is that order is like call1, call2, result1, result2, ...and I think there is something not right. It should be call1, result1, call2, result2, ...or am I wrong? I tried subscribing to observable2 in the onCompleteof observable1 but I think dedicated methods would be useless then. I have researched and found some solutions with subscribing to both observables simultaneously with concat but I just want the code to continue after getDepartments() when all data traffic is finished.

正如您所看到的,当组件被初始化时,它会调用两个获取数据的方法。这些方法从我的服务中获取 observables 并订阅它们。
问题是顺序就像call1, call2, result1, result2, ...我认为有些不对劲。应该是call1, result1, call2, result2, ...还是我错了?我尝试在 observable1 中订阅 observable2,onComplete但我认为专用的方法那时没有用。我已经研究并找到了一些使用 concat 同时订阅两个 observable 的解决方案,但我只希望代码在所有数据流量完成后在 getDepartments() 之后继续。

And should I unsubscribe in the OnDestroy()or in the OnCompleteof the subscribefunction I don't really get the difference?

我应该在OnDestroy()或 在我没有真正得到区别OnCompletesubscribe功能中取消订阅吗?

回答by Thierry Templier

If you want to control the execution order of observables, you need to build an asynchronous data flow leveraging operators like flatMap(execution in series) or Observable.forkJoin(execution in parallel)

如果你想控制 observables 的执行顺序,你需要利用像flatMap(execution in series) 或Observable.forkJoin(execution in parallel)这样的操作符来构建一个异步数据流

Here are samples:

以下是示例:

// Series
someObservable.flatMap(result1 => {
  return someOtherObservable;
}).subscribe(result2 => {
  (...)
  (...)
});

// Parallel
Observable.forkJoin([ someObservable, someOtherObservable ])
  .subscribe(results => {
    let result1 = results[0];
    let result2 = results[1];
  });

回答by BlueM

Usually, such calls are asynchronous, and in consequence, the order of execution and/or arriving results is not deterministic. (Example: When requesting data from API 1 and then from API 2, it might even result in data from API 2 arriving before data from API 1 if API 1 is especially slow or the amount of data is huge.) So, to answer your first question: yes, you are wrong.

通常,此类调用是异步的,因此,执行顺序和/或到达结果的顺​​序是不确定的。(例如:当从 API 1 请求数据然后从 API 2 请求数据时,如果 API 1 特别慢或者数据量很大,它甚至可能导致 API 2 的数据在 API 1 的数据之前到达。)所以,回答你的第一个问题:是的,你错了。

When subscribing to the Observable, you probably have some kind of callback function (the place where the data received is used or stored) which is executed by the 1st service once the data arrives. If it is important to trigger the 2nd API call only after receiving the result for the 1st call, this function would be the place to request data from the 2nd service. Of course, you will not want to couple service 1 and service 2, so a better approach would be to pass a callback function to service 1 which is to be invoked in case of success. Then, your client code can make sure that this callback function requests data from the 2nd service. Of course, there are numerous ways how to handle such cases, and what I described before is just a simple approach.

当订阅 Observable 时,你可能有某种回调函数(接收到的数据被使用或存储的地方),一旦数据到达,它就会由第一个服务执行。如果仅在收到第一次调用的结果后才触发第二次 API 调用很重要,则此函数将是从第二次服务请求数据的地方。当然,您不会希望将服务 1 和服务 2 耦合,因此更好的方法是将回调函数传递给服务 1,该函数将在成功时调用。然后,您的客户端代码可以确保此回调函数从第二个服务请求数据。当然,处理这种情况的方法有很多种,我之前描述的只是一个简单的方法。

Regarding the unsubscribing issue: often, it is not desired to unsubscribe when receiving results, as there might be more data coming in afterwards. (This is one of the key differences between Promises and Obvservables). For instance, in an application I am working on, I unsubscribe when “leaving” the component, as I dowant to keep on subscribing after I received initial data.

关于退订问题:通常情况下,在收到结果时不希望退订,因为之后可能会有更多数据进来。(这是 Promises 和 Obvservables 之间的主要区别之一)。例如,在我正在处理的应用程序中,我在“离开”组件时取消订阅,因为我确实希望在收到初始数据后继续订阅。