我需要RxJS专业人员的帮助:)
我尝试通过http请求从REST API递归加载数据。 递归调用工作正常,但是当我怀疑使用最终的Observable(由GetTemperatures返回)时,订阅中没有返回任何数据。
似乎没有数据在调用链中传回。
这是怎么了?
GetTemperatures().subscribe((data: MeasureData) => {
// add data to a chart, etc...
})
GetTemperatures(): Observable<MeasureData> {
const l_startDate = new Date(2019, 0, 1);
var l_httpParams = new HttpParams()
.set('device_id', this._deviceId)
.set('module_id', this._moduleId)
.set('scale', '1hour')
.set('type', 'Temperature')
.set('date_begin', Math.floor(l_startDate.getTime() / 1000).toString())
.set('real_time', 'true')
.set('optimize', 'true');
return this._http.post<MeasureDataInternal>(this._getMeasureUrl, l_httpParams)
.pipe(
map((data: MeasureDataInternal): MeasureData => this.transformMeasureData(data)),
flatMap((data: MeasureData) => {
return this.recursiveLoadData(data);
})
);
}
recursiveLoadData(data: MeasureData): Observable<MeasureData> {
// search until now minus 1,5 hours
const endDate = new Date(Date.now() - (1.5 * 60 * 60 * 1000));
console.error('RECURSIVE begin: ' + data.value[0].date + ' end: ' + data.value[data.value.length - 1].date);
// check if complete
if (data.value[data.value.length - 1].date.getTime() >= endDate.getTime()) {
console.error('recursive ENDs here');
return EMPTY;
}
var l_httpParams = new HttpParams()
.set('device_id', this._deviceId)
.set('module_id', this._moduleId)
.set('scale', '1hour')
.set('type', 'Temperature')
.set('date_begin', Math.floor(data.value[data.value.length - 1].date.getTime() / 1000).toString())
.set('real_time', 'true')
.set('optimize', 'true');
return this._http.post<MeasureDataInternal>(this._getMeasureUrl, l_httpParams)
.pipe(
map((data2: MeasureDataInternal): MeasureData => this.transformMeasureData(data2)),
flatMap((data2: MeasureData) => {
return this.recursiveLoadData(data2);
})
)
}
答案 0 :(得分:1)
我不知道,您实际上是想完成什么,但是递归中的每个新步骤除了将您带到下一步之外,没有任何其他作用。因此,您需要包括希望每个步骤执行的操作。
这不是特定于流的,一般递归也是如此。
这与常规递归函数的工作原理没有任何不同。假设您要递归地将数组中的数字相加,则需要将数组的尾部添加到第一个值。如果您只是继续在较小的数组上递归而不加总弹出的数字,那么您将获得基本情况的值。
这将返回数组的最后一个值(数组的最后一个值是基本情况):
recursiveAdd(array){
if(array.length === 1) return array[0];
return recursiveAdd(array.shift());
}
这将添加数组:
recursiveAdd(array){
if(array.length === 1) return array[0];
return array[0] + recursiveAdd(array.shift());
}
在这种简单情况下,+
操作数在递归的每个步骤中都在执行工作。没有它,该数组将无法汇总。而且,我当然可以做任何事情。从1000中减去该数组,对数组中的数字求平均值,然后从这些值中构建一个对象。 任何内容。
在进行递归调用之前,您必须做一些事情。除非您追求的是基本情况的价值(在您的情况下为空流)
将值合并映射到流中时,不会同时转发该值。
from([69,70,71]).pipe(
mergeMap(val => from([
String.fromCharCode(val),
String.fromCharCode(val),
String.fromCharCode(val)
]))
).subscribe(console.log);
输出
e e e f f f g g g
注意输出中不包含任何数字吗? mergeMap
时,您将值映射到流中。如果要映射的值成为流的一部分,则必须以某种方式包括它们。这与常规递归相同。
因此,这里有两个示例,都将您的数据包含在返回的流中。它们是非常基础的,但是希望您可以从中获得一些理解并将其应用。
这将转换返回的流以将您的数据作为其第一个值(当然是递归的)
return this._http.post<MeasureDataInternal>(this._getMeasureUrl, l_httpParams)
.pipe(
map((data: MeasureDataInternal): MeasureData =>
this.transformMeasureData(data)
),
mergeMap((data: MeasureData) =>
this.recursiveLoadData(data).pipe(
startWith(data)
)
)
);
这将创建数据流,递归调用流,并将两个流合并在一起。
return this._http.post<MeasureDataInternal>(this._getMeasureUrl, l_httpParams)
.pipe(
map((data: MeasureDataInternal): MeasureData =>
this.transformMeasureData(data)
),
mergeMap((data: MeasureData) =>
merge (
of(data),
this.recursiveLoadData(data)
)
)
);