如何创建一个随机间隔产生随机数的无限Observable?

时间:2016-12-29 22:41:02

标签: rxjs

给定一个生成随机数的函数,你会如何创建一个随机间隔产生随机数的无限Observable?

function getRandomNumber() {
  // Assume this function returns a random number, e.g. 198
}

function getRandomDelay() {
  // Assume this function returns a random delay in ms, e.g. 2000
}

以下是所需Observable的示例:

---198--------64-------3---2----------18------->  (indefinitely)

3ms     7ms       6ms   3ms     10ms

4 个答案:

答案 0 :(得分:9)

作为替代方案,如果您不想生活在令人困惑的超时世界中,您可以完全将其写为流:

// the stream
const randomizer$ = Rx.Observable.of("")
  .switchMap(() => Rx.Observable
             .timer(getRandomDelay())
             .mapTo(getRandomNumber()))
  .repeat();

// subscribe to it
randomizer$.subscribe(num => console.log("Random number after random delay" + num));


// your utility functions
function getRandomNumber() {
  return ~~(Math.random() * 200)
}

function getRandomDelay() {
  return Math.random() * 1000
}

这里的工作示例:http://jsbin.com/zipocaneya/edit?js,console

备选方案:首先创建随机数,然后添加延迟(如果执行时间无关紧要)

// the stream
const randomizer$ = Rx.Observable.of("")
  .switchMap(() => Rx.Observable
             .of(getRandomNumber())
             .delay(getRandomDelay()
  )
  .repeat();

// subscribe to it
randomizer$.subscribe(num => console.log("Random number after random delay" + num));

附加说明:由于流外部没有并发或异步操作,而不是switchMap,您也可以使用concatMap或{{ 1}} - 在这种情况下,它们都是一样的。

答案 1 :(得分:7)

const { Observable }  = require("rxjs");

const ob = new Observable(sub => {
  let timeout = null;

  // recursively send a random number to the subscriber
  // after a random delay
  (function push() {
    timeout = setTimeout(
      () => {
        sub.next(getRandomNumber());
        push();
      },
      getRandomDelay()
    );
  })();

  // clear any pending timeout on teardown
  return () => clearTimeout(timeout);
});

ob.subscribe(console.log);

答案 2 :(得分:0)

您能看看https://github.com/cszredwan/crazyObservable吗? 我敢肯定这会有所帮助,这是一个可观察到的习惯,可以在固定的时间范围内发出(随机!)固定数量的数据。

您的问题是随机使用的含义不精确。 crazyObservable绘制单个数据流,其中包含在指定时间范围内发出数据的所有可能性。当然,您可以合并crazyObservable的多个实例以获得所需的行为。

答案 3 :(得分:0)

在RxPY 3.0中,您可以使用以下结构:

res = rx.generate(0, lambda x: True, lambda x: x + 1).pipe(
         ops.map(lambda x: rx.timer(random.random() * 0.4).pipe(ops.map(lambda y: x))),
         ops.merge(max_concurrent=1),
         ops.map(lambda x: {'count': x, 'value': random.randint(0, 5)}))

这会在随机时间生成一个介于0到5之间的无限整数的无限流,到达间隔时间均匀地分布在[0,0.4]上。

在RxPY 3.0中,未实现switchmap或concatmap之类的操作(如@olsn的回复)。通过与max_concurrent = 1合并可以实现concat_all操作。

编辑:

rx.generate(0, lambda x: True, lambda x: x + 1)

正在阻止。使用无限的香草python生成器,例如

import itertools
r = rx.from_iterable(_ for _ in itertools.count(start=0, step=1))

也在阻止。您可以添加一些计划程序,例如

from rx.scheduler.eventloop import AsyncIOScheduler
from rx.scheduler import ThreadPoolScheduler
import multiprocessing

scheduler = AsyncIOScheduler(asyncio.get_event_loop())
# scheduler = ThreadPoolScheduler(multiprocessing.cpu_count()) # alternatively

res = rx.generate(0, lambda x: True, lambda x: x + 1).pipe(
         ops.map(lambda x: rx.timer(random.random() * 0.4).pipe(ops.map(lambda y: x))),
         ops.merge(max_concurrent=1),
         ops.map(lambda x: {'count': x, 'value': random.randint(0, 5)}),
         ops.subscribe_on(scheduler)
)