0

以下に示すように、例 1 で div を返し、次に別のクリック オブザーバブル flatMap を に返すと失敗するのはなぜclick$ですか?

例 2 は問題なく動作します。以下のJSBinを試してみてください

なぜこれが起こるのか誰でも説明できますか?私が理解していることから、flatMap は Observable を拡張します。 http://jsbin.com/sowodi/3/edit?js、コンソール、出力

// Example 1
() => {
  let stream = Rx.Observable.fromArray([1, 2, 3]);

  let div$ = stream.map(i => {
    let div = document.createElement('div');
    div.innerHTML = `NOT WORKING DIV ${i}`;
    return div;
  })

  div$.subscribe(div => {
    document.querySelector('body').appendChild(div);
  })

  let click$ = div$.flatMap(
    div => Rx.Observable.fromEvent(div, 'click')
  );

  click$.subscribe(click => console.log('click'));
}();


// Example 2
() => {
  let stream = Rx.Observable.fromArray([4, 5, 6]);

  let click$ = stream.flatMap(i => {
    let div = document.createElement('div');
    div.innerHTML = `DIV ${i}`;
    document.querySelector('body').appendChild(div);

    return Rx.Observable.fromEvent(div, 'click');
  })

  click$.subscribe(click => console.log('click'));
}();
<!DOCTYPE html>
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>

<body>
  <div id="app">
    THE APP ID
  </div>
</body>

</html>

4

1 に答える 1

0

これは、最初の例で 2 セットの div を作成しているためです。これと同等のことを行いました:

  Rx.Observable.fromArray([1, 2, 3])
    .map(i => {
      let div = document.createElement('div');
      div.innerHTML = `NOT WORKING DIV ${i}`;
      return div;
    }).subscribe(div => {
      document.querySelector('body').appendChild(div);
    })

  Rx.Observable.fromArray([1, 2, 3])
    .map(i => {
      let div = document.createElement('div');
      div.innerHTML = `NOT WORKING DIV ${i}`;
      return div;
  }).flatMap(
      div => Rx.Observable.fromEvent(div, 'click')
  ).subscribe(click => console.log('click'));

その理由は、各サブスクリプションがまったく新しい独立したものを作成し、作成した他のストリームに影響を与えないというfromArray冷たい意味を作成するためです.Observable

これを修正するには 2 つの方法があります。1) すでに発見した方法は、すべてのロジックを格納する単一のストリームのみを作成する方法、または 2) 代わりにObservable、すべてのサブスクリプションが実際に共有されるように div$ からの結果をホットにする方法です。同じストリーム。これには独自の問題があります。つまり、注意しないとメッセージを見逃す可能性がありますが、最初のケースをリファクタリングすると、次のようになります。

  let stream = Rx.Observable.fromArray([1, 2, 3]);

  let div$ = stream.map(i => {
    let div = document.createElement('div');
    div.innerHTML = `NOT WORKING DIV ${i}`;
    return div;
  })
  //Make div$ into a connectable Observable so the subscriptions will
  //share the underlying Observable
  .publish()

  div$.subscribe(div => {
    document.querySelector('body').appendChild(div);
  })

  let click$ = div$.flatMap(
    div => Rx.Observable.fromEvent(div, 'click')
  );

  click$.subscribe(click => console.log('click'));

  //Nothing happens until you call connect which subscribes to the underlying
  //Observable
  div$.connect();
于 2016-02-05T08:14:15.063 に答える