Javascript 如果完成,则RxJs取最后一个,否则在值之间插入延迟

Javascript 如果完成,则RxJs取最后一个,否则在值之间插入延迟,javascript,rxjs,Javascript,Rxjs,我会给出完整的解释,但基本上我需要确保 发出的值之间有一些延迟 如果观测值已完成,只需返回最新值 比 我有两个观测值,每个都发出0或1个值,然后完成: //1. lazy observable that emit 0 or two value created at time of subscription and then completes const cache$ = this.getFromCacheLazy(); //2. ReplaySubject, that emits v

我会给出完整的解释,但基本上我需要确保

  • 发出的值之间有一些延迟
  • 如果观测值已完成,只需返回最新值
  • 比 我有两个观测值,每个都发出0或1个值,然后完成:

     //1. lazy observable that emit 0 or two value created at time of subscription and then completes
     const cache$ = this.getFromCacheLazy();
    
     //2.  ReplaySubject, that emits value in 1-1500ms and completes
     const request$ = this.executeRequest(); 
    
    我将其组合为observable,即首先发出缓存值(如果有),然后请求值:

     const cacheAndRequest$ = concat(cache$, request$);
    
    一段时间后我订阅了它:

     setTimeout(() => {
         cacheAndRequest$.Subscribe(console.log);
     }, someDelay)
    
    我该怎么办 修改或管道
    缓存和请求$
    ,以便:

  • 如果订阅时,
    $request
    已完成, 必须忽略缓存$值

    • 提示:如果$request已完成,则cacheAndRequest$也将在订阅时完成
  • 如果订阅时,
    $request
    未完成,请立即从$cache发出值,并在500毫秒后从$request发出值。换句话说,这两个值之间必须存在延迟

  • 这里是运动场:


    复制代码

    为了实现这一点,我对您的
    缓存$
    请求$
    进行了一些修改,以识别可观察到的:

    const cache$ = getFromCacheLazy().pipe(
      map(cache => {
        return {source: 'cache', value: cache};
      })
    );
    
    const request$ = executeRequest().pipe(
      map(request => {
        return {source: 'request', value: request};
      })
    );
    
    我把
    concat
    留给你了

    然后我应用了
    withLatestFrom
    函数来获取最新的发射值。如果最新发出的值来自
    请求$
    我将返回它,否则我将连接可观测值以返回
    缓存$
    值,并至少等待500毫秒发出
    请求$

    const $subscribeDelayed = timer(subscriptionDelay)
      .pipe(
        withLatestFrom(cacheAndRequest$), // Provide the latest value from cacheAndRequest$
        switchMap(res => {
          // if request$ is already completed at the time of subscription, cache$ value is ignored
          // else cache$ is emitted and request$ is emitted after at least 500ms
          return res[1].source === 'request'
            ? of(res[1].value)
            : concat(
              of(res[1].value),
              request$.pipe(
                delay(500),
                map(res => res.value)
              )
            );
        }),
        tap(res => console.log(res)),
      );
    

    看。

    这是一个有趣的问题。我得考虑一下。我认为主要问题是,
    concat()
    无法帮助您完成
    请求$
    。您需要
    forkJoin()
    combinelatetest()
    ,尽管最后一个创建操作符将阻止任何发出的值,直到
    请求$
    给您一些信息。我想说,您需要
    merge()
    并为两个流提供一个
    startWith()
    ,这样就有了一个基本值。我不确定是否有RxJS有效的方法来检查其中一个流是否已经完成。
    CombineTest
    其中
    流有一个
    startWith()
    将允许您确定某种状态。它会给你像
    [value,0]
    之类的东西;当你要
    complete()
    时,你发送另一个值,比如
    1
    ,你会得到
    [value,1]
    ,并且能够确定逻辑上的差异。关于延迟的另一个想法取决于你的可观察对象的内部状态。您可以在之后
    switchMap()
    ,并在其中创建一个一次性可观察对象。根据确定的状态,您可以返回(值)的
    或(值)的
    管道(延迟(500))
    等等。解释起来有点复杂,但它会产生一个可读性很好的流。如果你更新了问题,请给我一个ping(在这里或在Twitter上)。我想这是一个有趣的问题,我很乐意去看看你们的操场。我已经更新了,见最后一行。之后,让我们删除评论。提示:我认为需求#1可以通过debounceTime(0)来解决,因为如果响应一点也不差,那么会将2个值合并为1。其实很简单。然而,我能够用
    去BounceTime(0)
    解决#2问题,这可以防止在订阅时完成可观察时同时执行缓存和响应。它可以工作,因为$cache总是在订阅时发出并完成