如何使用rxjs实现长池流?

时间:2018-03-13 11:00:12

标签: angular rxjs

  1. 我将angularService.method1称为id,我需要下一个请求
  2. 我想每秒致电angularService.method2(id),直到收到回复{success: true}或:

    {success: false, errors: [{errorCode: 'code', errorMessage: 'some error message'}]
    
  3. 经过几个小时的尝试,我来到了这个版本,实际上它可行。但我有一些问题

    1. 当主流达到“完成”时,内部Observable是否会被销毁?
    2. 这是一个正确的实现还是我在这里遇到了一些问题?

      this.angularService
      .method1(data)
      .flatMap((res) => {
          return Observable
              .interval(1000)
              .flatMap(() => this.angularService.method2(res.id))
              .concatMap(resp => {
                  return (resp.success) ? Observable.of(resp, null) : Observable.of(resp);
              })
              .takeWhile(resp => resp);
      })
      .switchMap((res) => {
          return (!res.success && res.errors) ? Observable.throw(res.errors) : Observable.of(res);
      })
      .subscribe(
          (next) => console.log(next),
          (err) => console.log(err),
          () => console.log('finished')
      );
      

1 个答案:

答案 0 :(得分:0)

我知道你要调用method2,直到得到第一个非null或未定义的响应,然后关闭流。

如果这是正确的,那么我会开始编写一个接收id参数的函数,然后每秒调用method2直到得到答案,如

callMethod2EverySecond(id) {
  return Observable.interval(1000)
         .mergeMap(() => this.angularService.method2(id))
         .filter(resp => resp !== null)
         .take(1)
}

此功能执行以下操作

  • 每秒调用method2,id为参数 - 假设为 method2返回一个对象(具有正确的响应或 错误)或null - 认为mergeMap是新的 名称flatMap
  • 过滤掉所有通过过滤器保留null的事件 operator
  • 使第一个事件不为null并关闭流 (这由take运营商执行)

然后你可以在外部逻辑中使用该函数,例如

this.angularService
.method1(data)
.switchMap(res => callMethod2EverySecond(res.id))
.subscribe(
    res => {
       if (!res.success && res.errors) {console.error(res)}
       else {console.log(res)}
    },
    (err) => console.log(err),
    () => console.log('finished')
);

考虑以下几点:

    在这种情况下,
  • switchMap和mergeMap(或flatMap)可能会产生 相同的结果,但不一样(read this for more details
  • 因为您可以通过分析内容来推断您的错误情况 响应,您可以直接在定义的第一个函数中执行此操作 作为subscribe的参数,您不需要抛出Observables 作为错误

使用angularService.method1和angularService.method2 模拟的工作代码示例

以下是根据上述假设的代码的工作示例。

method1method2已经模拟了angularService。

import {Observable} from 'rxjs';

method1('123')
.switchMap(res => callMethod2EverySecond(res.id))
.subscribe(
    res => {
       if (!res.success && res.errors) {console.error(res)}
       else {console.log('subscription processing', res)}
    },
    (err) => console.log(err),
    () => console.log('finished')
);

function callMethod2EverySecond(id) {
    return Observable.interval(10)
           .mergeMap(data => method2(id, data))
           .do(resp => console.log('resp', resp))
           .filter(resp => resp !== null)
           .take(1)
}

function method1(data: string) {
    return Observable.of({id: data});
}

function method2(id: string, interval: number) {
    const ret = randomIntInc(0,1) === 0 ? null : {success: true, errors: null, interval, id};
    return Observable
            .of(ret)
            .delay(randomIntInc(0,2000));
}

function randomIntInc(low, high) {
    return Math.floor(Math.random() * (high - low + 1) + low);
}
相关问题