如何在 Angular 2 中 "chain" 两个独立的 observables
How to "chain" two seperate observables in Angular 2
我正在使用 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()}
);
}
如您所见,当组件初始化时,它会调用两种获取数据的方法。这些方法从我的服务中获取可观察值并订阅它们。
问题是顺序就像 call1, call2, result1, result2, ...
,我认为有些地方不对。应该是 call1, result1, call2, result2, ...
还是我错了?我尝试在 observable1 的 onComplete
中订阅 observable2,但我认为专用方法将毫无用处。
我已经研究并找到了一些解决方案,通过 concat 同时订阅两个可观察对象,但我只希望代码在所有数据流量完成时在 getDepartments() 之后继续。
我应该在 OnDestroy()
中取消订阅还是在 subscribe
函数的 OnComplete
中取消订阅我真的不明白其中的区别?
通常,此类调用是异步的,因此,and/or 到达结果的执行顺序是不确定的。 (示例:当从 API 1 然后从 API 2 请求数据时,如果 API 1特别慢或者数据量很大。)所以,回答你的第一个问题:是的,你错了。
当订阅 Observable 时,您可能有某种回调函数(使用或存储接收到的数据的地方),一旦数据到达,它就会由第一个服务执行。如果仅在收到第一次调用的结果后才触发第二次 API 调用很重要,则此函数将是从第二个服务请求数据的地方。
当然,您不希望将服务 1 和服务 2 耦合,因此更好的方法是将回调函数传递给服务 1,以便在成功时调用该函数。然后,您的客户端代码可以确保此回调函数从第二个服务请求数据。当然,这种情况的处理方法有很多种,我之前介绍的只是一种简单的方法。
关于退订问题:通常,收到结果时不希望退订,因为之后可能会有更多数据进来。 (这是 Promises 和 Obvservables 之间的主要区别之一)。例如,在我正在处理的应用程序中,我在“离开”组件时取消订阅,因为我 想在收到初始数据后继续订阅。
如果你想控制可观察对象的执行顺序,你需要构建一个异步数据流,利用像flatMap
(串行执行)或Observable.forkJoin
(并行执行)这样的运算符
示例如下:
// Series
someObservable.flatMap(result1 => {
return someOtherObservable;
}).subscribe(result2 => {
(...)
(...)
});
// Parallel
Observable.forkJoin([ someObservable, someOtherObservable ])
.subscribe(results => {
let result1 = results[0];
let result2 = results[1];
});
我正在使用 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()}
);
}
如您所见,当组件初始化时,它会调用两种获取数据的方法。这些方法从我的服务中获取可观察值并订阅它们。
问题是顺序就像 call1, call2, result1, result2, ...
,我认为有些地方不对。应该是 call1, result1, call2, result2, ...
还是我错了?我尝试在 observable1 的 onComplete
中订阅 observable2,但我认为专用方法将毫无用处。
我已经研究并找到了一些解决方案,通过 concat 同时订阅两个可观察对象,但我只希望代码在所有数据流量完成时在 getDepartments() 之后继续。
我应该在 OnDestroy()
中取消订阅还是在 subscribe
函数的 OnComplete
中取消订阅我真的不明白其中的区别?
通常,此类调用是异步的,因此,and/or 到达结果的执行顺序是不确定的。 (示例:当从 API 1 然后从 API 2 请求数据时,如果 API 1特别慢或者数据量很大。)所以,回答你的第一个问题:是的,你错了。
当订阅 Observable 时,您可能有某种回调函数(使用或存储接收到的数据的地方),一旦数据到达,它就会由第一个服务执行。如果仅在收到第一次调用的结果后才触发第二次 API 调用很重要,则此函数将是从第二个服务请求数据的地方。 当然,您不希望将服务 1 和服务 2 耦合,因此更好的方法是将回调函数传递给服务 1,以便在成功时调用该函数。然后,您的客户端代码可以确保此回调函数从第二个服务请求数据。当然,这种情况的处理方法有很多种,我之前介绍的只是一种简单的方法。
关于退订问题:通常,收到结果时不希望退订,因为之后可能会有更多数据进来。 (这是 Promises 和 Obvservables 之间的主要区别之一)。例如,在我正在处理的应用程序中,我在“离开”组件时取消订阅,因为我 想在收到初始数据后继续订阅。
如果你想控制可观察对象的执行顺序,你需要构建一个异步数据流,利用像flatMap
(串行执行)或Observable.forkJoin
(并行执行)这样的运算符
示例如下:
// Series
someObservable.flatMap(result1 => {
return someOtherObservable;
}).subscribe(result2 => {
(...)
(...)
});
// Parallel
Observable.forkJoin([ someObservable, someOtherObservable ])
.subscribe(results => {
let result1 = results[0];
let result2 = results[1];
});