RxJs避免外部状态,但仍然可以访问先前的值

时间:2016-04-14 01:57:41

标签: javascript node.js reactive-programming rxjs

我正在使用RxJs来听amqp queu(不太相关)。

我有一个函数createConnection,它返回Observable,它会发出新的连接对象。一旦建立了连接,我希望每隔 1000ms 发送一次消息,然后在10封消息之后我想关闭连接。

我正在尝试避免外部状态,但如果我不将连接存储在外部变量中,我该如何关闭它?请参阅我从连接开始,然后是flatMap并推送消息,因此在几个链之后我不再拥有连接对象。

这不是我的流程,但想象一下这样的事情:

createConnection()
  .flatMap(connection => connection.createChannel())
  .flatMap(channel => channel.send(message))
  .do(console.log)
  .subscribe(connection => connection.close()) <--- obviously connection isn't here

现在我明白这样做是愚蠢的,但现在我该如何访问连接?我当然可以从var connection = createConnection()

开始

以后以某种方式加入。但是我该怎么做?我甚至不知道如何正确地提出这个问题。 Bottomline,我所拥有的是一个可观察的,发出连接,在连接打开后我想要一个每1000ms发出一次消息的observable(带take(10)),然后关闭连接

2 个答案:

答案 0 :(得分:5)

您问题的直接答案是&#34;您可以通过每个步骤进行操作&#34;。例如,您可以替换此行

.flatMap(connection => connection.createChannel())

这一个:

.flatMap(connection => ({ connection: connection, channel: connection.createChannel() }))

并保持对连接的访问​​权限。

但是,还有另一种方法可以做你想做的事。让我们假设你的createConnection和createChannel函数看起来像这样:

function createConnection() {
  return Rx.Observable.create(observer => {
    console.log('creating connection');
    const connection = {
      createChannel: () => createChannel(),
      close: () => console.log('disposing connection')
    };

    observer.onNext(connection);

    return Rx.Disposable.create(() => connection.close());
  });
}

function createChannel() {
  return Rx.Observable.create(observer => {
    const channel = {
      send: x => console.log('sending message: ' + x)
    };

    observer.onNext(channel);

    // assuming no cleanup here, don't need to return disposable
  });
}

createConnection(和createChannel,但我们会关注前者)会返回一个冷的观察者;每个订阅者将获得包含单个连接的自己的连接流,并且当该订阅到期时,将自动调用dispose逻辑。

这允许你做这样的事情:

const subscription = createConnection()
  .flatMap(connection => connection.createChannel())
  .flatMap(channel => Rx.Observable.interval(1000).map(i => ({ channel: channel, data: i })))
  .take(10)
  .subscribe(x => x.channel.send(x.data))
;

您实际上不必处理订阅以进行清理;在take(10)满意后,整个链将完成并将触发清理。您需要明确调用处理订阅的唯一原因是,如果您想在10个1000毫秒间隔之前解决问题。

请注意,此解决方案还包含对您的问题的直接答案的实例:我们将频道推到线下,以便我们可以在传递给订阅调用的onNext lambda中使用它(通常在此类代码出现的地方)

以下是整个工作:https://jsbin.com/korihe/3/edit?js,console,output

答案 1 :(得分:-1)

此代码给了我一个错误,因为flatmap等待 observable&lt;(T)&gt; ({connection:connection,channel:connection.createChannel()} )它是一个对象。

.flatMap(connection => ({ connection: connection, channel: connection.createChannel() }))

您可以使用 combineLatest 运算符

.flatMap(connection => Observable.combineLatest( Observable.of(connection), connection.createChannel(), (connection, channel) => { ... code .... });