angular - Angular 6 嵌套请求不提供正确的数据
问题描述
我订阅了两个相互嵌套的 httprequest。我的目的是让模型数组在第一个请求中充满对象,而不是发出第二个请求并订阅它,这样我就可以从第一个请求中修改对象。问题是在第二个请求中我做了很多对象操作,当我将它保存到存储中时,那些操作不存在..
private _patientListPoll$ = interval(this.listRequestInterval).pipe(
startWith(0),
map(() => this.getPatientList().subscribe(model=>{
this.model = model.map(a => Object.assign({}, a));
const linkedIds = this.model.filter(x => x.linkedUserId && x.statusId === 2).map(x => x.linkedUserId);
this.deviceDataService.getLastActivity(linkedIds).subscribe(data=>{
for (const item of data) {
let patient = this.model.find(x => x.linkedUserId === item.userId);
if (patient) {
Object.assign(patient, { lastActivity: item.lastUploadDate });
const diff = Math.abs(new Date().getTime() - new Date(patient.lastActivity).getTime());
const diffDays = Math.ceil(diff / (1000 * 3600 * 24));
if (diffDays <= 7) {
Object.assign(patient, { filterStatus: 4 });
}
let id = patient.id;
let index = this.model.findIndex(item => item.id === id)
this.model.splice(index, 1, patient)
console.log(this.model)
}
}
this.patientDataStore.savePatientData(this.model);
})
}), share()));
任何想法都会很棒..
在 bryan60 的大力帮助下,我明白了
private _patientListPoll$ = timer(0, this.listRequestInterval).pipe(
switchMap(() => this.getPatientList()),
switchMap(model => {
const linkedIds = model.filter(x => x.linkedUserId && x.statusId === 2).map(x => x.linkedUserId);
this.trialService.getPatientTrialStatusList().subscribe(data=>{
if (data) {
for (const item of data.result) {
for (const patient of model) {
if (item.id === patient.id) {
Object.assign(patient, {trialStatusId: item.state});
console.log(patient)
break;
}
}
}
}
})
return this.deviceDataService.getLastActivity(linkedIds).pipe(
map(data => {
for (const item of data) {
let patient = model.find(x => x.linkedUserId === item.userId);
if (patient) {
Object.assign(patient, {lastActivity: item.lastUploadDate});
const diff = Math.abs(new Date().getTime() - new Date(patient.lastActivity).getTime());
const diffDays = Math.ceil(diff / (1000 * 3600 * 24));
if (diffDays <= 7) {
Object.assign(patient, {filterStatus: 4});
}
let id = patient.id;
let index = model.findIndex(item => item.id === id);
model.splice(index, 1, patient);
}
}
return model;
})
);
}),
tap(model => {
this.patientDataStore.savePatientData(model);
this.model = model;
}),
share());
解决方案
您现在正在使用导致您的问题的“嵌套订阅”反模式。相反,通过使用适当的高阶可观察对象来避免嵌套订阅。
private _patientListPoll$ = timer(0, this.listRequestInterval).pipe( // prefer timer to interval and starts with
switchMap(() => // use switchMap to subscribe to inner observable and cancel previous subscriptions if still in flight
forkJoin(this.getPatientList(), this.trialService.getPatientTrialStatusList())), //forkJoin runs multiple observables in parrallel and returns an array of the values
switchMap(([model, trialData]) => { // now I have both model and trial data
// this.model = model.map(a => Object.assign({}, a)); don't produce side effects
use it as needed...
if (trialData) {
for (const item of trialData.result) {
for (const patient of model) {
if (item.id === patient.id) {
Object.assign(patient, {trialStatusId: item.state});
console.log(patient)
break;
}
}
}
}
const linkedIds = model.filter(x => x.linkedUserId && x.statusId === 2).map(x => x.linkedUserId);
return this.deviceDataService.getLastActivity(linkedIds).pipe(
map(data => { // now do your mapping since you've got both
for (const item of data) {
let patient = model.find(x => x.linkedUserId === item.userId);
if (patient) {
Object.assign(patient, { lastActivity: item.lastUploadDate });
const diff = Math.abs(new Date().getTime() - new Date(patient.lastActivity).getTime());
const diffDays = Math.ceil(diff / (1000 * 3600 * 24));
if (diffDays <= 7) {
Object.assign(patient, { filterStatus: 4 });
}
let id = patient.id;
let index = model.findIndex(item => item.id === id)
model.splice(index, 1, patient)
console.log(model)
}
}
return model;
})
);
}),
tap(model => { // prefer tap for side effects if absolutely necessary
this.patientDataStore.savePatientData(model);
this.model = model;
}),
share()
);
这也大大清理了您的管道。
与手头的问题不严格相关,但您可以稍微清理/简化您的地图逻辑:
map(data =>
model.map(patient => {
let toAssign = {};
const item = data.find(x => x.userId === patient.linkedUserId);
if (item) {
const lastActivity = item.lastUploadDate;
const diff = Math.abs(new Date().getTime() - new Date(lastActivity).getTime());
const diffDays = Math.ceil(diff / (1000 * 3600 * 24));
const filterStatus = (diffDays < 7) ? 4 : patient.filterStatus;
toAssign = {
lastActivity,
filterStatus
};
}
const trial = (trialData || []).find(t => t.id === patient.id);
if (trial) {
Object.assign(toAssign, {trialStatusId: trial.state});
}
return Object.assign({}, patient, toAssign);
})
)
推荐阅读
- ios - Swift 通用闭包总和
- javascript - Reactjs - 为什么我不能设置状态?
- visual-studio - 部署 SSRS 报告时 Visual Studio 崩溃
- php - PHP Laravel 无法连接到谷歌上的云 sql 可以 appengine
- vue.js - 从 vue 的下拉列表中选择选项时填充文本值
- react-native - React Native:使用可重用组件的 React Navigation
- javascript - 动态更改输出结果颜色
- r - R:为什么 PieDonut() 不可用?
- c# - wcf post 方法如何从传入请求中获取标头?
- html - 为什么 (display: flex) 表现得像继承的属性?