2017-11-12 10 views
1

私はRxJSに関する練習をしています。 そして、何かが非常に奇妙な出来事があります: RxJSはすべてのイベントを受け取るわけではありません

typoStream.subscribe(x => console.log('wont get executed')); 
    wordCompletedStream.subscribe(nextStream); 
    typoStream.subscribe(x => console.log('will get executed')); 

アプリケーションが最初にconsole.logを実行

が印刷され得ることはありません2つ目になります。
ストリームが何で、どのように相互作用しているかにかかわらず、これは決して起こらないはずです。私が観察可能なものを購読するときに重要なのはなぜですか?それはすべての購読者にイベントを送信してはいけませんか?

あなたはそれを試してみたい場合: http://embed.plnkr.co/xb8Yimo5RcYGPtgClYgY/

正しく表示された単語を入力し、あなたがアクションに「エラー」を参照してくださいすることができます。しかし、それはたびに起こるのではなく、たいていの場合にのみ起こります。

はここで、ストリームの流れです:https://photos.app.goo.gl/Z4cpKzekAIuKzMF93

+2

あなたは、とても親切してくださいこと、そして私たちのためにすべてをコピーしますか?また、コードの最小限の例を教えてください。 – smnbbrv

+2

さて、typoStreamにはフィルタが付いているので、タイプミスがあったときにだけ出力されます。タイプミスをしないと、決して発動しません。タイプミスをした場合は、両方とも購読します。また、入力が空の場合にreturnステートメントに欠陥があり、新しい単語に発火すると思います。 –

+0

こんにちは、私は可能な限りコードを減らそうとしました:http://embed.plnkr.co/xb8Yimo5RcYGPtgClYgY/ データの流れのグラフを作成しました:https://photos.app.goo.gl/Z4cpKzekAIuKzMF93 –

答えて

2

私はあなたが投稿コードでプレーしていた、とキーの修正が正しくcheckWord、観察をマルチキャストすることです。 wordStreamのように.publish().refCount()でこれを行うことができます。同じことを行うショートカットメソッド.share()を使用することもできます。この動作

const checkStream = wordStream.combineLatest(inputStream).share(); 

理由はないそれなしで、そのようなtypoStreamwordCompletedStreamとして複数checkStreamへのサブスクリプションまたはそれに由来する任意のストリームは、それぞれがマルチキャスト正確である(観察wordStreamに新しいサブスクリプションをトリガし、そうすることで新しいリクエストが作成されます)、入力に新しいイベントリスナーを登録するinputStreamが観測可能です。 .share()オペレータとの

、それはcheckStreamまたは派生観測に作られていますどのように多くのサブスクリプションの問題ではありません、最初のものだけがinputStreamにサブスクリプションをトリガします。

この修正の後、typoStreamへの2人のサブスクライバのどちらも、正しく入力された単語に対して発火しません。私はtypoStreamと呼ばれる観察可能なものから期待するものです。間違った文字が入力されると、両方とも起動します。

Forked Plunkr here

または、下記の抜粋を参照してください。

(() => { 
 

 
    // --- UI Stuff, NO NEED TO TOUCH THESE --- // 
 
    const wordField = $('#TotDWord'); 
 
    const inputField = $('#TotDInput'); 
 
    // ----------------------------------------- // 
 

 
    // A stream of the users string inputs 
 
    const inputFieldStream = Rx.Observable.fromEvent(inputField, 'keyup') 
 
    .map(x => x.target.value).distinctUntilChanged(); 
 

 
    // This stream is used to represent the users unput - we don't use the 
 
    // inputFieldStream directly because we want to manually send values aswell 
 
    const inputStream = new Rx.Subject(); 
 

 

 
    // Feed the stream from the field into our inputStream 
 
    inputFieldStream.subscribe(inputStream); 
 

 
    // A stream that allows us to manually trigger that we need a new word 
 
    const nextStream = new Rx.Subject(); 
 

 
    // When we want the next word we need to reset the users input 
 
    nextStream.subscribe(() => { 
 
    inputField.val(''); 
 
    inputStream.onNext(''); 
 
    }); 
 

 
    // This stream calls a server for a new random word every time the nextStream emits an event. We startWith a value to trigger the first word 
 
    const wordStream = nextStream.startWith('') 
 
    .flatMapLatest(getRandomWord) 
 
    // publish & refCount cache the result - otherwise every .map on wordStream would cause a new HTTP request 
 
    .publish().refCount(); 
 

 
    // When there is a new word, we display it 
 
    wordStream.subscribe(word => { 
 
    wordField.empty(); 
 
    wordField.append(word); 
 
    }); 
 

 
    // Checkstream combines the latest word with the latest userinput. It emits an array, like this ['the word', 'the user input']; 
 
    const checkStream = wordStream.combineLatest(inputStream).share(); 
 

 
    // Emits an event if the user input is not correct 
 
    const typoStream = checkStream.filter(tuple => { 
 
    const word = tuple[0]; 
 
    const input = tuple[1]; 
 
    return !word.startsWith(input); 
 
    }); 
 

 
    // When there is a typo we need a new word 
 
    typoStream.subscribe(nextStream); 
 

 
    // Emits an event when the user has entered the entire word correctly 
 
    const wordCompletedStream = checkStream.filter(tuple => { 
 
    const word = tuple[0]; 
 
    const input = tuple[1]; 
 
    return word == input; 
 
    }); 
 

 
    /** 
 
    * THIS WILL (MOST OF THE TIME) NOT FIRE WHEN YOU COMPLETE A WORD 
 
    */ 
 
    typoStream.subscribe(x => console.log('wont get executed')); 
 

 
    // Whenever the word is completed, request a new word 
 
    wordCompletedStream.subscribe(nextStream); 
 

 
    /** 
 
    * THIS WILL FIRE WHEN YOU COMPLETE A WORD 
 
    */ 
 
    typoStream.subscribe(x => console.log('will get executed')); 
 

 
    // Calls a server for a random word 
 
    // returns a promise 
 
    function getRandomWord() { 
 
    return $.ajax({ 
 
     // Change the URL to cause a 404 error 
 
     url: 'https://setgetgo.com/randomword/get.php' 
 
    }).promise(); 
 
    } 
 

 
})();
<script data-require="jquery" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script> 
 

 
<div> 
 
    <h1>Exercise: Typing of the Dead</h1> 
 
    <div> 
 
    Type the given word correctly and watch the console. Most of the time 1 of the 2 subscriptions on the typoStream will fire (when there should fire none). 
 
    </div> 
 
    <br /> 
 
    <div id="TotDWord"></div> 
 
    <input type="text" name="" id="TotDInput" value="" /><span>Highscore: </span><span id="TotDHighscore"></span> 
 
    <div id="TotDScore"></div> 
 
</div> 
 

 
<script> 
 
    console.clear(); 
 
</script>

+0

すごい、ありがとう!しかし、私は管理する必要があります、私はそれがどんなふうに振る舞っているのかをよく理解していません。なぜ、inputStreamの新しいサブスクリプションは、inputStream.onNext( '')を介してemityだった空の値の代わりに、inputFieldStreamから値を送出しますか? –

関連する問題