【问题标题】:RxJs emit after delay or next event on the streamRxJs 在延迟或流上的下一个事件后发出
【发布时间】:2018-04-30 02:52:03
【问题描述】:

我有一对事件:add1/add2/etc 和 remove1/remove2/etc。我想要以下内容:

  • add1 在流上发出时
    • 如果DELAY 没有新的add* 排放
      • 发射remove1
    • 如果发出add*
      • 立即为add1 发出remove1
      • DELAY 之后为add* 发出remove*

对于流中所有add* 的发射,这应该会继续。

这是我为这个案例使用 RxJS 大理石测试编写的一个测试:

import test from 'tape'
import { set, lensPath } from 'ramda'
import { TestScheduler } from 'rxjs/testing'
import hideAfterDelay from '../another/file'
import { actionCreators } from '../another/dir'

const prefix = 'epics -> notifications'

test(`${prefix} -> hideAfterDelay`, t => {
  t.plan(1)

  const scheduler = new TestScheduler(t.deepEqual)

  const actionMap = {
    a: createAddAction('hello!'),
    b: createAddAction('goodbye!'),
    x: actionCreators.notifications.remove('hello!'),
    y: actionCreators.notifications.remove('goodbye!')
  }

  scheduler.run(({ cold, expectObservable }) => {
    const actionStream = cold('a-------a-b-a------', actionMap)
    const expected =          '-----x-----x-y----x'
    const actual = hideAfterDelay(5)(actionStream)

    expectObservable(actual).toBe(expected, actionMap)
  })
})

function createAddAction (name) {
  const action = actionCreators.notifications.add(name)
  const lens = lensPath(['payload', 'id'])

  return set(lens, name, action)
}

认为该测试代表了我上面描述的以及我想要的行为。

我怎样才能写出这个 observable?我尝试过使用timerrace,但我无法让它工作......

这是一部使用redux-observable 的史诗,顺便说一句。

使用 RxJS v6

【问题讨论】:

    标签: rxjs redux-observable


    【解决方案1】:

    好的,我认为我使用闭包并稍微修改了我的测试断言得到了一个可行的解决方案。

    首先,预期的大理石图应该是这样的

    //   input:    a-------a-b-a------
    // - expected: -----x-----x-y----x
    // + expected: -----x----x-y----x
    //
    // Note above that the middle x and y emit at the same time as new
    // `add*` actions on the source stream instead of one frame later
    

    有了这个小改动——感觉仍然与我在问题中的描述一致——我能够通过以下方式通过测试:

    import { of, timer, empty } from 'rxjs'
    import { switchMap, mapTo, tap, merge } from 'rxjs/operators'
    import { ofType } from '../operators'
    import actionTypes from '../../actionTypes/notifications'
    import { actionCreators } from '../..'
    
    export default (delay = 3000) => actionStream => {
      let immediateRemove
    
      return actionStream.pipe(
        ofType(actionTypes.ADD),
        switchMap(action => {
          let obs = empty()
    
          if (immediateRemove) {
            obs = of(immediateRemove)
          }
    
          const remove = actionCreators.notifications.remove(action.payload.id)
    
          immediateRemove = remove
    
          return obs.pipe(
            merge(
              timer(delay).pipe(
                tap(() => {
                  immediateRemove = null
                }),
                mapTo(remove)
              )
            )
          )
        })
      )
    }
    

    我不知道这是否是解决问题的最佳或正确方法,但我相当肯定这是一种方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-25
      • 1970-01-01
      • 2017-07-24
      • 1970-01-01
      • 2017-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多