Angular 通过RxJS操作符限制可观测的网络请求
我有一些数据通过网络请求进入Angular应用程序的一个组件。这是一个可观察的,看起来像这样:Angular 通过RxJS操作符限制可观测的网络请求,angular,typescript,rxjs,Angular,Typescript,Rxjs,我有一些数据通过网络请求进入Angular应用程序的一个组件。这是一个可观察的,看起来像这样: this.streamFiltersService.getByFilters( this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'], this.location = filters['location'], this.zipcode = filt
this.streamFiltersService.getByFilters(
this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'], this.location = filters['location'],
this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
this.branch = filters['branch'], fn);
let fn = resRecordsData => {
this.records = resRecordsData;
};
public onFilterReceived(values)
{
let filters = {};
if (values) {
filters = values;
}
this.route.params.subscribe(
(params: any) => {
this.page = params['page'];
}
);
console.log('onFilterReceived() firing...');
let fn = resRecordsData => {
this.records = resRecordsData;
};
this.streamFiltersService.getByFilters(
this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'], this.location = filters['location'],
this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
this.branch = filters['branch'], fn);
}
这里有一个名为fn
的回调,如下所示:
this.streamFiltersService.getByFilters(
this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'], this.location = filters['location'],
this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
this.branch = filters['branch'], fn);
let fn = resRecordsData => {
this.records = resRecordsData;
};
public onFilterReceived(values)
{
let filters = {};
if (values) {
filters = values;
}
this.route.params.subscribe(
(params: any) => {
this.page = params['page'];
}
);
console.log('onFilterReceived() firing...');
let fn = resRecordsData => {
this.records = resRecordsData;
};
this.streamFiltersService.getByFilters(
this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'], this.location = filters['location'],
this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
this.branch = filters['branch'], fn);
}
我遇到的问题是,随着过滤器的大量启动进入组件,我最终会收到多个网络请求——对于用户来说,屏幕数据会发生多次更改。此外,因为这是异步的,所以有时第一个请求中的一个会最后返回,并且过滤器不会应用到用户看到的屏幕中
完整函数如下所示:
this.streamFiltersService.getByFilters(
this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'], this.location = filters['location'],
this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
this.branch = filters['branch'], fn);
let fn = resRecordsData => {
this.records = resRecordsData;
};
public onFilterReceived(values)
{
let filters = {};
if (values) {
filters = values;
}
this.route.params.subscribe(
(params: any) => {
this.page = params['page'];
}
);
console.log('onFilterReceived() firing...');
let fn = resRecordsData => {
this.records = resRecordsData;
};
this.streamFiltersService.getByFilters(
this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'], this.location = filters['location'],
this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
this.branch = filters['branch'], fn);
}
作为后续操作,当我在onFilterReceived()
内的回调上放置console.log
时,如下所示:
let fn = async resRecordsData => {
console.log('records: ', resRecordsData);
this.records = await resRecordsData;
};
public async onFilterReceived(values)
{
let filters = {};
if (values) {
filters = values;
}
this.route.params.subscribe(
(params: any) => {
this.page = params['page'];
}
);
console.log('onFilterReceived() firing...');
let fn = async resRecordsData => {
await resRecordsData
.distinctUntilChanged()
.debounceTime(1000)
.switchMap( resRecordsData => {
this.records = resRecordsData;
});
console.log('records: ', this.records);
};
this.streamFiltersService.getByFilters(
this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'], this.location = filters['location'],
this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
this.branch = filters['branch'], fn);
}
打印到控制台的内容如下:
records: {ok: true, status: 200, statusText: "OK", data: Array(1), count: 1}
records: {ok: true, status: 200, statusText: "OK", data: Array(12), count: 115}
records: {ok: true, status: 200, statusText: "OK", data: Array(1), count: 1}
records: {ok: true, status: 200, statusText: "OK", data: Array(1), count: 1}
records: {ok: true, status: 200, statusText: "OK", data: Array(1), count: 1}
records: {ok: true, status: 200, statusText: "OK", data: Array(12), count: 115}
records: {ok: true, status: 200, statusText: "OK", data: Array(12), count: 115}
records: {ok: true, status: 200, statusText: "OK", data: Array(12), count: 115}
records: {ok: true, status: 200, statusText: "OK", data: Array(12), count: 115}
records: {ok: true, status: 200, statusText: "OK", data: Array(12), count: 115}
请注意,因为我应用了一个过滤器,所以正确的值是数组(1)。正如您所看到的,因为这些调用是异步的,所以它们会出现顺序错误。理想情况下,我只需要一个电话,结果如下:
records: {ok: true, status: 200, statusText: "OK", data: Array(1), count: 1}
根据下面的建议,我尝试将建议的运算符链接到onFilterReceived()
的回调中,如下所示:
let fn = async resRecordsData => {
console.log('records: ', resRecordsData);
this.records = await resRecordsData;
};
public async onFilterReceived(values)
{
let filters = {};
if (values) {
filters = values;
}
this.route.params.subscribe(
(params: any) => {
this.page = params['page'];
}
);
console.log('onFilterReceived() firing...');
let fn = async resRecordsData => {
await resRecordsData
.distinctUntilChanged()
.debounceTime(1000)
.switchMap( resRecordsData => {
this.records = resRecordsData;
});
console.log('records: ', this.records);
};
this.streamFiltersService.getByFilters(
this.page - 1, this.pagesize, this.currentStage, this.language = filters['language'], this.location = filters['location'],
this.zipcode = filters['zip'], this.firstName = filters['firstName'], this.lastName = filters['lastName'],
this.branch = filters['branch'], fn);
}
。。。但我最后犯了一个错误:
error_handler.js:60 error:Uncaught(承诺中):TypeError:
resRecordsData.distinctUntilChanged不是一个函数
因此,如果我正确理解您的问题:
- 您可以通过异步回调来维护全局状态(
)this.records
- http请求被触发,但返回时没有顺序
$filterChanges
.distinctUntilchanged()
.debounceTime(1000)
.switchMap(filters => getByFilters(.....))
.subscribe(records => {
// modify global state with the records
});
因此,您首先获取过滤器流及其更改—例如{page,pagesize,currentStage,language}
。您可能必须为filters对象的distinctunitChanged
添加compareFunc
,因为它是非原语
下面是一个粗略的非角度实现示例,可以帮助您:
/*使我们的html过滤器元素可见*/
var carTypeFilter=document.getElementById('cars');
var hornsCheckbox=document.getElementById('horns');
var$carsFilter=Rx.Observable.fromEvent(carTypeFilter,'change')
.map(evt=>({filter:'car',value:evt.target.value}));
var$hornsFilter=Rx.Observable.fromEvent(hornsCheckbox,“更改”)
.map(evt=>({filter:'horns',value:evt.target.checked}));
/*我们希望有一个值包含过滤器的当前逻辑分组*/
var$filtersCombined=Rx.Observable.merge($carsFilter,$hornsFilter)
.scan((allCurrentFilters,currFilterItem)=>{
allCurrentFilters[currFilterItem.filter]=currFilterItem.value;
返回所有当前过滤器;
}, {});
变量$debouncedFilterChanges=$filtersCombined
/*对于DistinctUntil,更改为工作
您需要使用compareFunction进行计算
如果过滤器的所有键:值对都相同
在本例中不打算这样做;它只会过滤掉
单击Frantic后设置过滤器,但只会导致额外的
正在对后端执行请求*/
//.distinctUntilChanged()
/*对于每一个不同的过滤器,都要改变其亮度
我们知道用户已经不再摆弄输入了*/
.去BounceTime(500);
变量$filteredServerResults=$debouncedFilterChanges
.switchMap(filters=>getFilteredData(filters.car,filters.horns));
$filteredServerResults.subscribe(数据=>{
document.getElementById('results').innerText=JSON.stringify(数据);
});
/*
模拟对服务器进行异步调用的模拟函数,响应速度较慢
*/
函数getFilteredData(汽车、喇叭){
//请注意,汽车或喇叭可能未定义
返回Rx.Observable.of(`retrieved value for:${car}-${horns}`)
.delay(1500);//模拟慢速响应,用户可能已经询问了更新的结果
}
JS-Bin
选择一个。。。
沃尔沃汽车
萨博
梅赛德斯
奥迪
汽车
哈肖恩
结果。。。
如果我正确理解您的问题:
- 您可以通过异步回调来维护全局状态(
)this.records
- http请求被触发,但返回时没有顺序
$filterChanges
.distinctUntilchanged()
.debounceTime(1000)
.switchMap(filters => getByFilters(.....))
.subscribe(records => {
// modify global state with the records
});
因此,您首先获取过滤器流及其更改—例如{page,pagesize,currentStage,language}
。您可能必须为filters对象的distinctunitChanged
添加compareFunc
,因为它是非原语
下面是一个粗略的非角度实现示例,可以帮助您:
/*使我们的html过滤器元素可见*/
var carTypeFilter=document.getElementById('cars');
var hornsCheckbox=document.getElementById('horns');
var$carsFilter=Rx.Observable.fromEvent(carTypeFilter,'change')
.map(evt=>({filter:'car',value:evt.target.value}));
var$hornsFilter=Rx.Observable.fromEvent(hornsCheckbox,“更改”)
.map(evt=>({filter:'horns',value:evt.target.checked}));
/*我们希望有一个值包含过滤器的当前逻辑分组*/
var$filtersCombined=Rx.Observable.merge($carsFilter,$hornsFilter)
.scan((allCurrentFilters,currFilterItem)=>{
allCurrentFilters[currFilterItem.filter]=currFilterItem.value;
返回所有当前过滤器;
}, {});
变量$debouncedFilterChanges=$filtersCombined
/*对于DistinctUntil,更改为工作
您需要使用compareFunction进行计算
如果过滤器的所有键:值对都相同
在本例中不打算这样做;它只会过滤掉
单击Frantic后设置过滤器,但只会导致额外的
正在对后端执行请求*/
//.distinctUntilChanged()
/*对于每一个不同的过滤器,都要改变其亮度
我们知道用户已经停止