识别和准确识别 RxJS 中的一系列事件

Recognizing and exact series of events in RxJS

使用 RxJS,如果用户输入 'a' 然后 'b' 然后 'c',我想触发一个事件。

如果他们输入 'a' 然后 'b' 然后 'z' 然后 'c'.

我不希望触发事件

这是我 codepen 目前所做的工作(在 TypeScript 中)。

class App1 {
    private divStream: HTMLElement;
    private divResult: HTMLElement;

    constructor(divStream: HTMLElement, divResult: HTMLElement) {
            this.divStream = divStream;
            this.divResult = divResult;
    }

    start() {
        var filterByCharacter = (expectedCharater) => {
            return (char) => { return char === expectedCharater; };
        };

        var values = ['a', 'b', 'b', 'c', 'b'];

        var obChars = Rx.Observable.fromArray(values);
        obChars.subscribe((k) => {
            divStream.innerHTML += "<div style='color: blue'>" + ":: " + k + " ::" + "</div>";
                },
            (err) => {
                divStream.innerHTML += "<div style='background-color: blue' > " + 'Error: ' + err + " </div>";
            },
            () => {
                divStream.innerHTML += "<div style='background-color: blue'>" + ":: finished ::" + "</div>";
            }
        );

        function log(text: string) {
            divResult.innerHTML += "<div style='color: green'>" + text + "</div>";
        }
        var obA: Rx.Observable<string> = obChars.filter(filterByCharacter('a'));
        var obB: Rx.Observable<string> = obChars.filter(filterByCharacter('b'));
        var obC: Rx.Observable<string> = obChars.filter(filterByCharacter('c'));

        let aSteps: Rx.Observable<any>[] = [];
        aSteps.push(obA.take(1).do(() => { log("a"); }).ignoreElements());
        aSteps.push(obB.take(1).do(() => { log("b"); }).ignoreElements());
        aSteps.push(obC.take(1).do(() => { log("c"); }));
        let steps: Rx.Observable<any> = Rx.Observable.concat<any>(aSteps);
        var source = steps
            .takeUntil(Rx.Observable.timer(100 * values.length));

              var subscription = source.subscribe(
            function (x) {
                log("Next: " + x);
            },
            function (err) {
                divResult.innerHTML += "<div style='background-color: green'>Error: " + err + "</div>";
            },
            function () {
                divResult.innerHTML += "<div style='background-color: green' > " + 'Completed' + "</div>";
            });
    }

    stop() {
        clearTimeout(this.timerToken);
    }

}

window.onload = () => {
    var app = new App1(document.getElementById('divStream'), document.getElementById('divResult'));
    app.start();
};

我相信您正在寻找 bufferWithCount

从 RxJSNext 中查看这个 spec(接下来重命名为 bufferCount):

it('should emit full buffer then last partial buffer if source completes', function () {
  var e1 =   hot('--a^-b--c--d--e--|');
  var e1subs =      '^             !';
  var expected =    '--------y-----(z|)';

  expectObservable(e1.bufferCount(3)).toBe(expected, {
                                             y: ['b', 'c', 'd'],
                                             z: ['e']
                                           });
  expectSubscriptions(e1.subscriptions).toBe(e1subs);
 });

这似乎有效,它使用 simple state machine 并且可以泛化以识别任何基本的正则表达式。这里识别的正则表达式是 *abc* :

function noop () {}

var keyUp$ = 
  Rx.Observable.fromEvent(ta_input, 'keyup')
               .map(function(ev){return ev.keyCode});

var stateMachine$ = keyUp$
  .scan(function (state, keyCode) {
    if (String.fromCharCode(keyCode) === state.password[state.index]) {
      state.index++;
      if (state.index === state.password.length) {
        state.found = true;
      }
    } 
    else {
      state.index = 0;
      state.found = false;
    }
    return state;
}, {password : 'ABC', index : 0, found: false})
  .filter(function (state){return state.found})
  .take(1)

stateMachine$.subscribe(noop)

要检查它,运行 jsffidle,然后在文本区域中键入 abc。出于某种原因,您的密码必须大写,但这部分应该很容易修复。当检测到 abc 子字符串时,stateMachine$ observable 发出 found 并完成。