如何根据rxjs中的缓冲区内容缓冲一个observable?

时间:2017-01-07 17:21:24

标签: javascript rxjs reactive-programming

我想根据缓冲区的内容刷新缓冲的observable,但是如何实现呢?我想要做的简化示例:

observable.buffer(() => {
  // Filter based on the buffer content.
  // Assuming an observable here because buffer()
  // needs to return an observable.
  return buffer.filter(...);
})

以下是我尝试对关键事件(bin trick)进行的具体操作:

const handledKeySequences = ['1|2']

// Mock for document keydown event
keyCodes = Rx.Observable.from([1,2,3,4])

keyCodes
  .buffer(() => {
    /*
      The following doesn't work because it needs to be an
      observable, but how to observe what is in the buffer?
      Also would like to not duplicate the join and includes
      if possible
      return function (buffer) {
        return handledKeySequences.includes(buffer.join('|'));
      };
    */

    // Returning an empty subject to flush the buffer
    // every time to prevent an error, but this is not
    // what I want.
    return new Rx.Subject();
  })
  .map((buffer) => {
    return buffer.join('|')
  })
  .filter((sequenceId) => {
    return handledKeySequences.includes(sequenceId);
  })
  .subscribe((sequenceId) => {
    // Expecting to be called once with 1|2
    console.log("HANDLING", sequenceId)
  })

我觉得我的方法是错误的,但我无法弄清楚正确的做法是什么。我尝试过使用scan,但会扫描observable中的所有事件,这不是我想要的。

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

这应该适用于bufferWithCount

const handledKeySequences = ['1|2']

// Mock for document keydown event
keyCodes = Rx.Observable.from([0,1,2,3,4]);

const buffer$ = keyCodes
  .bufferWithCount(2, 1)  // first param = longest possible sequence, second param = param1 - 1
  .do(console.log)
  .map((buffer) => {
    return buffer.join('|')
  })
  .filter((sequenceId) => {
    return handledKeySequences.includes(sequenceId);

  });

  buffer$.subscribe((sequenceId) => {
    console.log("HANDLING", sequenceId)
  });

查看实时here

另请查看this问题。

答案 1 :(得分:0)

似乎这个功能目前在Rxjs中不可用,所以正如@olsn所建议的那样,我编写了一个自定义运算符,它通过传递一个函数来判断何时刷新缓冲区:

(function() {

  // Buffer with function support.
  function bufferWithContent(bufferFn) {
    let buffer = [];

    return this.flatMap(item => {
      buffer.push(item);
      if (bufferFn(buffer)) {
        // Flush buffer and return mapped.
        let result = Rx.Observable.just(buffer);
        buffer = [];
      } else {
        // Return empty and retain buffer.
        let result = Rx.Observable.empty();
      }
      return result;
    });
  }

  Rx.Observable.prototype.bufferWithContent = bufferWithContent;

})();

我还打开了一个问题here,建议添加此功能。