创建和侦听具有动态负载的 HTTP 可观察对象的正确方法
Proper way to create and listen to a HTTP observable with dynamic payload
场景
用户有一个菜单,该菜单创建了一组汽车标准,用于过滤出服务器端的结果。
当用户点击 Load 按钮时,它会发送条件集以获得正确的结果,然后将它们传递给 child 组件进行显示。
我正在尝试通过创建一个可观察对象来正确地做到这一点,虽然它有效,但它闻起来不对。
Parent HTML
<h3>Select Criteria</h3>
<div>
<!-- Bunch of dropdowns and radio buttons and gizmos that form the filter menu omitted for brevity-->
</div>
<button (click)="loadCars()">Load Cars</button>
<child-comp-table [dataSet]="results$ | async"><child-comp-table>
Parent TS
var _results$ = new BehaviorSubject<any[]>([]);
readonly results$ = this._results$.asObservable();
loadCars() {
// construct payload based on selected criteria and store in postPayload variable
this.http.post(url, postPayload).subscribe((res:any) => {
this._results$.next(res.data);
});
}
这是设置它的正确方法吗,我的担心源于我必须订阅而不是使用现有管道这一事实。
this.http.post(url, postPayload)
returns 一个 Observable,所以我不明白你为什么订阅它并将结果“保存”在行为主题中。
我会按照以下方向进行:
let results$ = of([]); // init the obs with an observable containing empty list
loadCars() {
this.results$ = this.http.post(url, postPayload);
}
顺便说一下,我也会取出对其自身服务的 HTTP 调用,但那是另一回事
在类似情况下,我倾向于的是以下
- 有服务class,例如
carService
,“调用 http”逻辑的地方
carService
公开了一个 API 方法,可以调用该方法来触发调用(例如 loadcars(postPayload)
)
carService
还公开了一个 Observable(例如 loadCarsResult$
)作为 API,任何想要收到调用结果通知的人都必须订阅 loadCarsResult$
carService
的实现和你开发的非常相似,只是抽离成一个单独的服务,像这样
@Injectable({
providedIn: 'root',
})
export class carService {
private _results$ = new BehaviorSubject<any[]>([]);
public results$ = this._results$.asObservable();
loadCars(postPayload) {
// pass the _result$ Subject to the subscribe method, which ensures that
// next, error and complete are correctly invoked
this.http.post(url, postPayload).subscribe(this._results$);
}
}
这样你就创建了一个“多播”机制。换句话说,许多组件可以 subscribe
到相同的 result$
Observable,并且所有组件都将在 http 调用的结果到达时立即更新。
看待同一件事的另一种方式是认为您已将 http 调用的调用与返回结果的使用分开。
场景
用户有一个菜单,该菜单创建了一组汽车标准,用于过滤出服务器端的结果。 当用户点击 Load 按钮时,它会发送条件集以获得正确的结果,然后将它们传递给 child 组件进行显示。
我正在尝试通过创建一个可观察对象来正确地做到这一点,虽然它有效,但它闻起来不对。
Parent HTML
<h3>Select Criteria</h3>
<div>
<!-- Bunch of dropdowns and radio buttons and gizmos that form the filter menu omitted for brevity-->
</div>
<button (click)="loadCars()">Load Cars</button>
<child-comp-table [dataSet]="results$ | async"><child-comp-table>
Parent TS
var _results$ = new BehaviorSubject<any[]>([]);
readonly results$ = this._results$.asObservable();
loadCars() {
// construct payload based on selected criteria and store in postPayload variable
this.http.post(url, postPayload).subscribe((res:any) => {
this._results$.next(res.data);
});
}
这是设置它的正确方法吗,我的担心源于我必须订阅而不是使用现有管道这一事实。
this.http.post(url, postPayload)
returns 一个 Observable,所以我不明白你为什么订阅它并将结果“保存”在行为主题中。
我会按照以下方向进行:
let results$ = of([]); // init the obs with an observable containing empty list
loadCars() {
this.results$ = this.http.post(url, postPayload);
}
顺便说一下,我也会取出对其自身服务的 HTTP 调用,但那是另一回事
在类似情况下,我倾向于的是以下
- 有服务class,例如
carService
,“调用 http”逻辑的地方 carService
公开了一个 API 方法,可以调用该方法来触发调用(例如loadcars(postPayload)
)carService
还公开了一个 Observable(例如loadCarsResult$
)作为 API,任何想要收到调用结果通知的人都必须订阅loadCarsResult$
carService
的实现和你开发的非常相似,只是抽离成一个单独的服务,像这样
@Injectable({
providedIn: 'root',
})
export class carService {
private _results$ = new BehaviorSubject<any[]>([]);
public results$ = this._results$.asObservable();
loadCars(postPayload) {
// pass the _result$ Subject to the subscribe method, which ensures that
// next, error and complete are correctly invoked
this.http.post(url, postPayload).subscribe(this._results$);
}
}
这样你就创建了一个“多播”机制。换句话说,许多组件可以 subscribe
到相同的 result$
Observable,并且所有组件都将在 http 调用的结果到达时立即更新。
看待同一件事的另一种方式是认为您已将 http 调用的调用与返回结果的使用分开。