我有一对事件:add1
/ add2
/ etc和remove1
/ remove2
/等。我喜欢以下内容:
add1
时
DELAY
发生,没有新的add*
排放
remove1
add*
remove1
发出add1
remove*
add*
发出DELAY
对于流上的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)
}
我认为测试代表了我上面描述的和我想要的行为。
我怎么写这个可观察的?我已尝试使用timer
和race
,但我还没有能够使用此功能......
这是一部使用redux-observable,btw。
的史诗使用RxJS v6
答案 0 :(得分:0)
好的,我认为我使用了一个闭包并稍微修改了我的测试断言的工作解决方案。
首先,预期的大理石图应该如下所示
// 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)
)
)
)
})
)
}
我不知道这是解决问题的最佳或正确方法,但我确信这是 方式。