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

Recognizing and exact series of events in RxJS

本文关键字:一系列 事件 RxJS 识别      更新时间:2023-09-26

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

如果他们输入"a"然后"

b"然后"z"然后"c",我不希望事件被触发。

这是我到目前为止所做的工作的代码笔(在 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();
};

这似乎有效,它使用一个简单的状态机,并且可以泛化以识别任何基本的正则表达式。此处识别的正则表达式是 *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$可观察量发出found并完成。

我相信

你正在寻找bufferWithCount。

查看来自 RxJSNext 的这个规范(在 next中重命名为 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);
 });