javascript - 当它已经完成以角度获取数据时如何一一显示数据
问题描述
HTML
<div nz-row *ngIf="tempThermometer | async as temp">
<div *ngFor="let data of temp;let i = index;" nz-col nzXs="24" nzSm="12" nzMd="12" nzXl="8" nzXXl="6">
<nz-spin nzTip="Loading..." [nzSize]="'large'" [nzSpinning]="data.spinning">
<div echarts [options]="chartOption[i]" [autoResize]="true" style="height: 270px;"></div>
</nz-spin>
</div>
</div>
TS
tempLoading = false;
tempThermometer = new BehaviorSubject<any>([]);
getRoomList() {
this.tempLoading = true;
this.subscription = this.global
.getData(`/conditions/latest?length=${this.pageSize}`)
.pipe(take(1))
.subscribe((res: any) => {
this.tempThermometer.next(Object.values(res['data'].map((obj: any) => {
return {
...obj,
spinning: true
};
})));
this.tempLoading = false;
this.lineChart(this.tempThermometer.value);
});
}
lineChart(params?: any) {
const _this = this;
const list: any = [];
params.forEach((param: any) => {
const url = encodeURIComponent(param.sensor);
// List URL
list.push(`/conditions?length=${this.length}&sensor=${url}`);
});
// Promise requests
const promises = list.map(
(url: any) =>
new Promise(resolve => {
this.subscription = this.global.getData(url).pipe(take(1)).subscribe((res) => {
resolve(res);
}, (err: Error) => {
return reject(err);
});
})
);
// Retrieve each data as per promise
Promise.all(promises).then(results => {
const dataRoom: any = [];
results.map((result) => {
const date: any = [], temperature: any = [], humidity: any = [], newRoomData: any = [];
const param = result['data'];
const roomData = orderBy(param, ['date'], ['asc']);
const room = roomData.slice(-1)[0];
const timeEnd = room.date.slice(0, 19);
const timeStart = subHours(timeEnd, 7);
const dataHour = roomData.filter((data: TemplogRecord) => {
return !isBefore(data.date, timeStart) && !isAfter(data.date, timeEnd);
});
// console.log(roomData);
const hash = Object.create(null);
dataHour.forEach((data: any) => {
const key = data.date.slice(0, 13);
if (!hash[key]) {
hash[key] = {
sensor: data.sensor, temperature: data.temperature,
humidity: data.humidity, date: key + ':00:00'
};
newRoomData.push(hash[key]);
}
});
for (let x = 0; x < newRoomData.length; x++) {
temperature.push(newRoomData[x].temperature);
humidity.push(newRoomData[x].humidity);
date.push(newRoomData[x].date);
}
dataRoom.push({
date: date,
humidity: humidity,
temperature: temperature
});
});
dataRoom.forEach((param: any, index: number) => {
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
animation: false
},
backgroundColor: 'rgba(245, 245, 245, 0.8)',
borderWidth: 1,
borderColor: '#ccc',
padding: 10,
textStyle: {
color: '#000'
},
formatter: function (prm: any) {
let rec = prm[0].name.slice(0, 10) + '<br/>' + prm[0].name.slice(11, 19) + '<br/>';
for (let x = 0; x < prm.length; x++) {
if (prm[x].axisIndex !== 1) {
rec += prm[x].marker + ' ' + prm[x].seriesName + ': '
+ prm[x].data + _this.units['Celcius'] + '<br/>';
} else {
rec += prm[x].marker + ' ' + prm[x].seriesName + ': '
+ prm[x].data + '%' + '<br/>';
}
}
return rec;
}
},
...this.echart.roomChart,
dataZoom: [{
type: 'inside',
show: false,
bottom: 0,
width: '84%',
xAxisIndex: [0, 1],
zoomOnMouseWheel: false,
},
{
type: 'slider',
bottom: 0,
show: false,
width: '84%',
xAxisIndex: [0, 1],
zoomLock: false,
}],
xAxis: [{
type: 'category',
boundaryGap: false,
scale: true,
axisLine: {
show: false
},
axisTick: {
show: false
},
data: param.date.map((str: any) => {
return format(str, 'YYYY-MM-DD hh:mm a');
}),
splitLine: {
show: true,
lineStyle: {
color: 'rgba(182, 202, 227)'
}
},
axisLabel: {
show: true,
interval: 0,
rotate: 90,
formatter: ((data: any) => {
return (data).slice(11, 19);
})
}
},
{
gridIndex: 1,
show: false,
scale: true,
type: 'category',
boundaryGap: false,
axisLine: {
show: false
},
data: param.date,
axisTick: {
show: false
},
splitLine: {
show: true
}
}],
series: [{
name: 'Humidity',
data: param.humidity,
type: 'line',
itemStyle: {
color: 'rgba(0, 101, 144, 1)'
},
markPoint: {
type: 'Pin',
data: [
{
type: 'max',
itemStyle: {
color: 'rgba(0, 101, 144)'
}
},
{
type: 'min',
itemStyle: {
color: 'rgb(110, 151, 204)'
}
}
]
},
smooth: true,
xAxisIndex: 1,
yAxisIndex: 1
},
{
name: 'Temperature',
data: param.temperature,
type: 'line',
itemStyle: {
color: 'rgba(255, 0, 0, 1)'
},
markPoint: {
type: 'Pin',
data: [
{
type: 'max',
itemStyle: {
color: 'rgba(255, 5, 0)'
}
},
{
type: 'min',
itemStyle: {
color: 'rgb(255, 87, 86)'
}
}
]
},
smooth: true
},
]
};
this.chartOption.push(option);
this.notScrolly = true;
this.tempThermometer.value.filter((x: any) => params.map((y: any) => {
if (y.id === x.id) {
return y.spinning = false;
}
}));
});
});
}
这里的问题是,当它加载时,它会在显示所有数据之前获取所有数据。我在这里要做的是,当第一个项目已经获取时,它将显示,而其他项目仍在获取数据。
例如有 5 个项目,即区域 1、区域 2、区域 3、区域 4 和区域 5。
当区域 1 已经完成获取数据时,它将显示它。而另一个仍在加载/获取。
就像区域 1 已经完成获取,然后是区域 3,然后是区域 2,然后是区域 5,然后是 4。
谁完成获取它会自动显示。
解决方案
我会以两种方式之一来解决这个问题。两者都不会涉及承诺。
我不会尝试使用您的代码示例,因为它太大了,相反,我将专注于您的问题的核心 - 运行一组可观察对象并在返回结果时对其进行处理。
1. 合并 observables
RxJSmerge
函数将一起运行多个 observable,并立即使用各个值调用您的订阅回调。
const observables: Observable<any>[] = this.getObservables();
merge(...observables).subscribe(result => {
// individual results are logged here as soon as the observable returns them
console.log(result);
}, err => {
// empty error callback.
// This is here to allow us to add the complete callback
}, () => {
console.log('complete');
});
优点:订阅结果处理简单
缺点:必须在完整的回调中运行完整的代码
2.管道中的处理结果
您可以在forkJoin
. 只有在最终的 observable 完成时才会调用 subscribe,但您可以在单个tap
运算符中处理结果。
const observables: Observable<any>[] = this.getObservables()
.map(x => x.pipe(
// tap is run as soon as the observable is returned
tap(result => console.log(result))
));
forkJoin(observables).subscribe(result => {
console.log('complete');
});
Pro:订阅中的简单完整处理
单个运算符中的Con处理结果tap
可能会有点混乱
结论
这两种方法是相当等价的。我可能更喜欢这种forkJoin
方法,但我想通过给你第二个例子来展示 RxJS 的强大和灵活性。
演示:https ://stackblitz.com/edit/angular-7rrmtn
该演示设置了 5 个可观察对象,每个对象都有不同的延迟。在返回结果时处理 observables,并在完成时记录它们。
如您所见,它们在功能上是等效的。
推荐阅读
- android - CheckBox.isChecked() 未返回预期值
- ionic-framework - 离子中的Tensorflowjs
- azure - Service Fabric 中每个服务的应用程序
- django - 让 django rest 框架 jwt 身份验证工作 [django rest, angular 5]
- android - 使用 gpio-keys 中断唤醒 RPi3 上的屏幕
- twig - amp-list src url 未获取数据
- python - Python解析模块搜索
- java - BST 中的水平遍历。队列不合作
- php - 快速PHP分页不起作用
- javascript - 在对话框中单击按钮时将今天的日期传递给 EditText 变量