在首次挂起之后跳过可观察到的排放量

时间:2018-03-12 20:00:25

标签: rxjs reactive-programming rxjs5 redux-observable

var button = document.querySelector('button');

var obs1 = Rx.Observable.fromEvent(button, 'click').scan(count => count + 1, 0).multicast(new Rx.Subject())

function obs2$(result) {
  return Rx.Observable.of(result).delay((Math.random() * 10000 % 2000) + 1000)
}

obs1.concatMap((count) => {
  return obs2$(count)
}).subscribe(x => console.log("Sync Finished " + x))

obs1.subscribe(x => console.log("Sync Request  " + x))

obs1.connect()
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/@reactivex/rxjs@5.3.0/dist/global/Rx.js"></script>

<button>Click me</button>

<h3 id='show'>Foo</h3>

我正在实现一个有两个可观察对象的同步系统。一个是同步请求操作流:

actions$.ofType('SYNC_REQUESTED')
在这种情况下,

actions$是表示Redux操作的redux-observable构造。

另一个observable执行实际同步,并在完成时调度Redux操作。

我希望它表现得如果当前正在执行同步,并且对同步请求进行另一次发射可观察,则同步排队(就像concatMap的情况一样)。但是,如果在同步期间进行多次发射,则实际上只有其中一种发射。

换句话说,我想要一个不会取消当前同步的switchMap

如果您运行附加的代码段并在一秒钟内连续五次点击该按钮,您会看到:

Sync Request  1
Sync Request  2
Sync Request  3
Sync Request  4
Sync Request  5
Sync Finished 5

如果您使用switchMap

使用concatMap您会看到:

Sync Request  1
Sync Request  2
Sync Request  3
Sync Request  4
Sync Request  5
Sync Finished 1
Sync Finished 2
Sync Finished 3
Sync Finished 4
Sync Finished 5

我想读它:

Sync Request  1
Sync Request  2
Sync Request  3
Sync Request  4
Sync Request  5
Sync Finished 1
Sync Finished 5

现在因为我正在使用Redux,我总是可以使用商店帮助我,可能跟踪syncPendingsyncInProgress标志并使用skipWhile来跳过同时发生的同步请求如果已经有一个挂起,则正在进行同步。

我想知道是否有办法通过使用RxJS来做到这一点,因为这需要额外的代码/动作/减少器/ Redux状态。

1 个答案:

答案 0 :(得分:0)

尝试take(1)和repeat()

var button = document.querySelector('button');

var obs1 = Rx.Observable.fromEvent(button, 'click').scan(count => count + 1, 0).multicast(new Rx.Subject())

function obs2$(result) {
  return Rx.Observable.of(result).delay(2000)
}


Rx.Observable.merge(obs1.audit(()=>obs1.mergeMap(obs2$)),
obs1.take(1).mergeMap(obs2$).repeat())
.subscribe(console.log)

obs1.subscribe(x => console.log("Sync Request  " + x))
obs1.connect()
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/@reactivex/rxjs@5.3.0/dist/global/Rx.js"></script>

<button>Click me</button>

<h3 id='show'>Foo</h3>