在 angular 中使用 observables 进行 http 请求的最佳方式是什么?
What is the best way to use observables for http requests in angular?
我有一个 Angular 应用程序可以从 API 获取数据。
所以首先我的 detail.component.ts 代码看起来有点像这样:
//code
getData()
{
this.http.get(url1).subscribe(data1 =>
{/*code: apply certain filter to get a filtered array out*/
this.http.get(url2).subscribe(data2 =>
{/*code: apply certain filter to get a filtered array out*/
this.http.get(url3).subscribe(data3 =>
{/*code: apply certain filter to get a filtered array out*/
})//closing third subscribe form
})//closing second subscribe form
})//closing first subscribe form
}
如您所见,由于所有这些调用相互嵌套,我以后的调用越多,就会越乱。我做了一些研究,发现 observables 可能会解决问题。所以我更改了代码,这就是现在的样子 - data.service.ts:
//code
getData1()
{this.data1 = this.http.get(this.url1)
return this.data1;}
getData2()
{this.data2 = this.http.get(this.url2)
return this.data2;}
getData3()
{this.data3 = this.http.get(this.url3)
return this.data3;}
detail.component.ts:
//code
ngOnInit()
{
this.dataService.getData1().subscribe(data1 =>
{/*code: apply certain filter to get a filtered array out*/
this.dataService.getData2().subscribe(data2 =>
{/*code: apply certain filter to get a filtered array out*/
this.dataService.getData3().subscribe(data3 =>
{/*code: apply certain filter to get a filtered array out*/
})//closing third subscribe form
})//closing second subscribe form
})//closing first subscribe form
}
Data1必须先执行,因为Data2和Data3需要过滤后的Array的信息来自 Data1。这就是为什么我努力应用像 forkJoin 这样的解决方案的原因。所以我的问题是,这是否是一个好的解决方案,或者您是否知道更好的方法来减少代码的混乱并保持功能?
你可以尝试异步等待方法
async ngOnInit() {
const data1 = await this.dataService.getData1().toPromise();
// apply certain filter to get a filtered array out
const data2 = await this.dataService.getData2().toPromise();
// apply certain filter to get a filtered array out
const data3 = await this.dataService.getData3().toPromise();
// apply certain filter to get a filtered array out
}
您也可以尝试合并地图
this.dataService.getData1()
.pipe(
map((data1) => {
// code: filter data here
return data1;
}),
mergeMap((data1) => {
this.dataService.getData2();
})
)
.subscribe((finalData) => {
});
或concatMap
this.dataService.getData1()
.pipe(
tap(data1 => console.log(data1)),
concatMap((data1) => {
this.dataService.getData2(data1);
}),
tap(data2 => console.log(data2)),
concatMap((data2) => {
this.dataService.getData3(data2);
}),
tap(data3 => console.log(data3)),
)
.subscribe(result => {
console.log(result)
});
使用 switchMap 运算符在 observable 之间切换...
this.dataService.getData1().pipe(
switchMap(data1 => {
// do whatever with data1
return this.dataService.getData2()
}),
tap(data2 => {
// do whatever with data2
return this.dataService.getData3()
})
).subscribe()
关于链接Rxjs,因为这是一个经常被问到的问题,你可以参考一些以前在SO上问过的问题,其中:
How to do the chain sequence in rxjs
Observable 可以提供大量的方法和工具来创建美观且可读的管道。这是一个例子:
// my.service.ts
getData1(): Observable {
return this.httpClient.get();
}
getData2(): Observable {
return this.httpClient.post();
}
getData3(): Observable {
return this.httpClient.get();
}
my.component.ts
ngOnInit() {
this.myService.getData1().pipe(
map(data => {
// do what you want with the request answer
data.id += 1;
return data;
}),
// Pass the modified data and return the Observable for the getData2 request
switchMap(data => this.myService.getData2(data)),
// RxJs have a ton of feature to let you play with the data and the pipeline
// This will wait for 2000ms
delay(2000),
// Pass the data returns by getData2 requests to the method getData3
switchMap(data => this.myService.getData3(data)),
).subscribe(
data => console.log(data); // The result of your pipeline
)
}
这里发生了什么:
- getData1() 被调用并将 return 我们的 HttpRequest
的 Observable
- 我们修改之前请求的结果(增加id)
- 我们使用修改后的结果来调用 getData2,它 return 是请求的 Observable
- 我们等待 2000 毫秒以继续
- 我们使用getData2请求的结果调用getData3
- 我们订阅此管道以获取最终结果
If you do not subscribe to a pipeline, it will never be triggered
RxJs 是一个非常庞大且不错的数据库,但是太多人不知道如何用好它。
要使用该库,您只需遵循一件事:
- 永远不要将 Observable 放入 Observable 中
部分问题参考(感谢@LingVu):
How to do the chain sequence in rxjs
我有一个 Angular 应用程序可以从 API 获取数据。 所以首先我的 detail.component.ts 代码看起来有点像这样:
//code
getData()
{
this.http.get(url1).subscribe(data1 =>
{/*code: apply certain filter to get a filtered array out*/
this.http.get(url2).subscribe(data2 =>
{/*code: apply certain filter to get a filtered array out*/
this.http.get(url3).subscribe(data3 =>
{/*code: apply certain filter to get a filtered array out*/
})//closing third subscribe form
})//closing second subscribe form
})//closing first subscribe form
}
如您所见,由于所有这些调用相互嵌套,我以后的调用越多,就会越乱。我做了一些研究,发现 observables 可能会解决问题。所以我更改了代码,这就是现在的样子 - data.service.ts:
//code
getData1()
{this.data1 = this.http.get(this.url1)
return this.data1;}
getData2()
{this.data2 = this.http.get(this.url2)
return this.data2;}
getData3()
{this.data3 = this.http.get(this.url3)
return this.data3;}
detail.component.ts:
//code
ngOnInit()
{
this.dataService.getData1().subscribe(data1 =>
{/*code: apply certain filter to get a filtered array out*/
this.dataService.getData2().subscribe(data2 =>
{/*code: apply certain filter to get a filtered array out*/
this.dataService.getData3().subscribe(data3 =>
{/*code: apply certain filter to get a filtered array out*/
})//closing third subscribe form
})//closing second subscribe form
})//closing first subscribe form
}
Data1必须先执行,因为Data2和Data3需要过滤后的Array的信息来自 Data1。这就是为什么我努力应用像 forkJoin 这样的解决方案的原因。所以我的问题是,这是否是一个好的解决方案,或者您是否知道更好的方法来减少代码的混乱并保持功能?
你可以尝试异步等待方法
async ngOnInit() {
const data1 = await this.dataService.getData1().toPromise();
// apply certain filter to get a filtered array out
const data2 = await this.dataService.getData2().toPromise();
// apply certain filter to get a filtered array out
const data3 = await this.dataService.getData3().toPromise();
// apply certain filter to get a filtered array out
}
您也可以尝试合并地图
this.dataService.getData1()
.pipe(
map((data1) => {
// code: filter data here
return data1;
}),
mergeMap((data1) => {
this.dataService.getData2();
})
)
.subscribe((finalData) => {
});
或concatMap
this.dataService.getData1()
.pipe(
tap(data1 => console.log(data1)),
concatMap((data1) => {
this.dataService.getData2(data1);
}),
tap(data2 => console.log(data2)),
concatMap((data2) => {
this.dataService.getData3(data2);
}),
tap(data3 => console.log(data3)),
)
.subscribe(result => {
console.log(result)
});
使用 switchMap 运算符在 observable 之间切换...
this.dataService.getData1().pipe(
switchMap(data1 => {
// do whatever with data1
return this.dataService.getData2()
}),
tap(data2 => {
// do whatever with data2
return this.dataService.getData3()
})
).subscribe()
关于链接Rxjs,因为这是一个经常被问到的问题,你可以参考一些以前在SO上问过的问题,其中:
How to do the chain sequence in rxjs
Observable 可以提供大量的方法和工具来创建美观且可读的管道。这是一个例子:
// my.service.ts
getData1(): Observable {
return this.httpClient.get();
}
getData2(): Observable {
return this.httpClient.post();
}
getData3(): Observable {
return this.httpClient.get();
}
my.component.ts
ngOnInit() {
this.myService.getData1().pipe(
map(data => {
// do what you want with the request answer
data.id += 1;
return data;
}),
// Pass the modified data and return the Observable for the getData2 request
switchMap(data => this.myService.getData2(data)),
// RxJs have a ton of feature to let you play with the data and the pipeline
// This will wait for 2000ms
delay(2000),
// Pass the data returns by getData2 requests to the method getData3
switchMap(data => this.myService.getData3(data)),
).subscribe(
data => console.log(data); // The result of your pipeline
)
}
这里发生了什么:
- getData1() 被调用并将 return 我们的 HttpRequest 的 Observable
- 我们修改之前请求的结果(增加id)
- 我们使用修改后的结果来调用 getData2,它 return 是请求的 Observable
- 我们等待 2000 毫秒以继续
- 我们使用getData2请求的结果调用getData3
- 我们订阅此管道以获取最终结果
If you do not subscribe to a pipeline, it will never be triggered
RxJs 是一个非常庞大且不错的数据库,但是太多人不知道如何用好它。
要使用该库,您只需遵循一件事:
- 永远不要将 Observable 放入 Observable 中
部分问题参考(感谢@LingVu):
How to do the chain sequence in rxjs