长处理大数组的每个元素后的可观察延迟

时间:2017-10-28 13:27:47

标签: javascript rxjs observable rxjs5

假设我们有一个大数组,并且该数组中每个元素的处理需要很长时间(5s)。我们想在处理下一个元素之前添加一些延迟(2s)。

我有点成功地实现了这样的行为:

let arr = [1, 2, 3]
let i = 0

Rx.Observable.of(null)
.map(val => arr[i++])
.do(val => {
  console.log(val + ' preloop')
  let time = +new Date() + 5000; while (+new Date() < time) {}
  console.log(val + ' afterloop')
})
.delay(2000)
.flatMap(val => (i < arr.length) ? Rx.Observable.throw(null) : Rx.Observable.empty())
.retry()
.subscribe(console.log, console.log, () => console.log('completed'))

输出符合预期:

1 preloop
delay 5s
1 afterloop
delay 2s
2 preloop
...
completed

但是这段代码很丑陋,不可重复使用且有错误,并且不符合rx的原则。有什么更好的方法?

请注意,数组(或者它可能根本不是数组)很大,而https://stackoverflow.com/a/21663671/2277240在这里不起作用。

虽然我可以想到一些用例,但这个问题是假设的。

2 个答案:

答案 0 :(得分:1)

我不确定为什么数组在这里非常重要,您可以使用您提供的链接中的相同方法解决问题。

对于长时间的操作,更好的做法可能是一个承诺。我使用异步睡眠功能来模拟5秒钟的操作,你可以用你的诺言替换它。

额外延迟的技巧是连接一个虚拟元素,将其延迟然后忽略它。

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

Rx.Observable.from([1, 2, 3])
  .concatMap(item => 
    Rx.Observable.defer(() => sleep(5000))
      .mapTo(item)
      .concat(Rx.Observable.of(null).delay(2000).ignoreElements()) 
  )
  .subscribe(console.log, console.log, () => console.log('completed'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script>

答案 1 :(得分:0)

延迟的替代方案,不会延迟第一次发射,

<form action="{{route('store')}}" method="POST">