使用RxJS,如果用户键入'a'然后'b'然后'c',我想触发一个事件。
Using RxJS, I want to fire an event if the user types 'a' then 'b' then 'c'.
如果他们输入'a'然后'b'然后'z'然后'c',我不希望事件被触发。
I do not want the event fired if they enter 'a' then 'b' then 'z' then 'c'.
这是我迄今为止所做工作的 codepen (在TypeScript中) )。
Here is my codepen of the work I have done so far (in 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 *:
This seems to be working, it uses a simple state machine and is generalizable to recognize any basic regular expression. The regular expression recognized here is *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 textarea。出于某种原因,您的密码必须是大写,但该部分应该很容易修复。当检测到 abc 子字符串时, stateMachine $ observable发出 found 并完成。
To check it, run the jsffidle, and type abc in the textarea. For some reason, your password has to be in caps, but that part should be easy to fix. When the abc substring is detected, the stateMachine$ observable emits found and completes.
更多推荐
认识RxJS中的一系列事件
发布评论