递归可观察调用不返回数据

时间:2020-11-11 19:30:01

标签: javascript typescript recursion rxjs observable

我需要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);
        })
      )

}

1 个答案:

答案 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)
    )
  )
);