为什么concatMap没有订阅所有groupBy Observables rxjs?

时间:2018-02-25 14:29:09

标签: rxjs rxjs5

我有一个问题,为什么这不是写入控制台数字2,4,6?是什么解释?

max

2 个答案:

答案 0 :(得分:2)

基本问题是,只有当前一个Observable完成时,才会使用concatMap订阅下一个Observable。 groupBy会发出两个GroupedObservable,所以它订阅了第一个,我认为它可以订阅链完成的第二个。这意味着观察者会收到来自第一个complete的{​​{1}}通知,因此您永远不会看到来自第二个GroupedObservable的值(说实话我并非100%确定它真的发生了像这样,但没有进一步调查你的例子是有意义的。)

因此,如果您只想要第二组:

GroupedObservable

查看实时演示(开放式控制台):https://stackblitz.com/edit/rxjs5-sfused

我检查了源代码,import { Observable } from 'rxjs'; Observable.range(1, 6) .groupBy(n => n % 2 === 0) .filter(o => o.key === true) .concatMap(obs => obs) .subscribe((n) => console.log(n), null, () => console.log('complete concatMap')) 在收到groupBy通知后(在收到complete的所有值后通知)完成了所有群组,因此永远不会有空间range订阅第二个Observable。

请参阅:https://github.com/ReactiveX/rxjs/blob/master/src/internal/operators/groupBy.ts#L200-L210

答案 1 :(得分:1)

问题是groupBy运算符为每个键发出Subjects

Concat映射仅在第一个Subject完成后才订阅后续的Subject,即,由于所有子流同时发出值,因此错过了从后续subjectSelector捕获项目的机会。

恭喜:https://blog.angularindepth.com/those-hidden-gotchas-within-rxjs-7d5c57406041

TL; DR:

GroupBy收到ReplaySubject作为第四个参数。您可以使用它来强制使用Subject而不是Observable.range(1, 6) .groupBy( n => n % 2 === 0, null, null, () => new ReplaySubject() // <-- Here we go ) .concatMap(obs => obs) .subscribe((n) => console.log(n)) (默认)

class MiglayoutExample extends JFrame {

static JFrame frame;
public static void main(String[] args) {
    frame = new JFrame("frame");

    JPanel bluePanel = new JPanel();
    bluePanel.setLayout(new MigLayout());
    bluePanel.setBackground(Color.BLUE);

    JPanel redPanel = new JPanel();
    redPanel.setBackground(Color.RED);

    bluePanel.add(redPanel, "width 100%, height 100%");

    frame.add(bluePanel);

    frame.setSize(600, 600);
    System.out.println("bluePanel.getHeight() = " + bluePanel.getHeight()); //Output 0
    System.out.println("bluePanel.getWidth() = " + bluePanel.getWidth());       //Output 0
    System.out.println("redPanel.getHeight() = " + redPanel.getHeight());       //Output 0
    System.out.println("redPanel.getWidth() = " + redPanel.getWidth());         //Output 0

    frame.show();
}
}

Demo on RxViz