rxjs-缓冲发出的值,直到其他可观察到的发出,然后照常发出

时间:2020-07-13 21:43:00

标签: rxjs

我正在构建一个记录器对象,该对象异步获取IP地址,然后使用该IP地址记录所有值。它必须在实例化之前就开始收集日志,但是只有在获得IP地址之后才发出日志。然后它应该会正常发光。

这是我的课程:


class LoggerService {
  constructor() {
    let thisIp;
    const getIp = Observable.create(function(observer) {
      // doing it with a timeout to emulate bad network
      setTimeout(() => {
        fetch('https://api.ipify.org?format=json').then(response => response.json()).then(response => {
          thisIp = response.ip;
          console.log('fetched IP: ', thisIp);
          observer.next(response.ip);
          observer.complete();
        });
      }, 5000)
    });
    // this is where I plan to buffer logs until IP is obtained
    this.logStream = new Subject().pipe(buffer(getIp));
    // for starters - just log to the console with the IP address
    this.logStream.subscribe((value) => console.log(thisIp, value));

  }

  emit = (message) => this.logStream.next(message);
}

但是它不能按我的需要工作;它确实将所有缓冲的值作为数组输出,但是在获得IP后停止发出它们:


const logger = new LoggerService();


setInterval(() => {
  logger.emit('Hey ' + Math.random())
}, 1000);

// I get five messages and that's it

即使缓冲后,如何使它发出我的值?

2 个答案:

答案 0 :(得分:1)

您不需要“缓冲”本身的值,而是可以创建一个依赖于异步ipAddress$的流,因此只有在发出ip地址后,该值才会被发出。 。 combineLatest可以很好地达到此目的。

让我们为LoggerService提供一个称为message$的消息流和一个简单的log()方法,该方法将提供的字符串推入该流。

我们可以构造一个messagesWithIpAddresses$流,该流使用combineLatest创建一个可观察对象,该对象与ipAddress$一起发出所提供的消息,但前提是两者都已经发出一个值。 / p>

export class LoggerService {
  private messages$ = new Subject<string>();

  public log(message: string): void {
    this.messages$.next(message);
  }

  constructor(service: GenericService) { 

    const messagesWithIpAddresses$ = this.messages$.pipe(
      mergeMap(message => combineLatest(service.ipAddress$, of(message)))
    );

    messagesWithIpAddresses$.subscribe(
      ([ip, message]) => {
        // actual logging logic would go here...
        console.log(`[${ip}] ${message}`);
      }
    );
  }
}

由于of(message)将立即发出,因此我们仅在等待ipAddress$。但是,如果已经发出一个值,那么它也将是即时的。

查看此有效的StackBlitz

screen cast sample

答案 1 :(得分:0)

更新:以下答案无效。查看buffer documentation之后 您的记录器Subject()仍然不会发出任何消息,因为它仅在getIp触发时才触发。在您的代码中,在http请求之后,getIp仅触发一次。

我认为我们需要您想要实现的目标的更多细节,以便提出正确的rxjs管道。


我将删除此行

observer.complete();  // remove it

这表明下标流已结束,这就是为什么您不再收到任何消息的原因了。