当内部订阅更改时,为什么在外部订阅范围中设置的变量会更改

时间:2019-05-25 17:13:18

标签: javascript angular rxjs observable state

我有以下6号角代码:

ngOnInit() {
    this.route.queryParams.subscribe((params: Params) => {
        const stuffId: string = params.stuffId;

        this.service.getState().subscribe((state) => {
            if (stuffId) {
                const specificStuff: Array<Stuff> = state.stuff.filter((s) => s.id === stuffId);

                const specificState: State = {
                    stuff: specificStuff,
                    tableData: this.service.getTableModel(specificStuff),
                    chartData: this.service.getChartModel({ stuff: specificStuff }),
                    hasAssetId: true,
                };

                this.data = specificState;
            } else {
                this.data = state;
            }
        });
    });
}

可观察到的this.service.getState()可能会多次获取新数据,但是this.route.queryParams不会获取新数据,除非查询参数发生更改

但是,通过设置调试断点,我看到查询参数'stufId'更新时,'stuffId'的初始值是我期望的值(UUID),但是当内部订阅(状态服务)更新了'外部作用域中的stuffId的值变为“未定义”-然后另一个状态更新再次用id填充它。这造成了“口吃”;在视图中。

我不明白内部作用域如何改变外部作用域,因为内部作用域从未访问过'stuffId'。一些我不理解的rxjs东西?

1 个答案:

答案 0 :(得分:1)

  

我不明白内部作用域如何改变外部作用域,因为内部作用域从未访问过'stuffId'。一些我不理解的rxjs东西?

这是因为this.route.queryParams发出一个以上的值。

每次发出值时,都会为this.service.getState()进行 new 订阅,内部subscribe()超时将触发重叠调试中断。从调试器的角度来看,您可能没有意识到自己正在同时调试两个或多个订阅。

this.data = statethis.data = specificState执行此操作后,视图模板就会闪烁

我建议您学习如何在Rxjs中使用switchMapmergeMap运算符,而不是从另一个订阅中调用subscribe。您只应为即将完成的短暂可观察性调用内部订阅。

this.route.queryParams
    .pipe(
        map((params: Params) => params.stuffId),
        switchMap(stuffId => combineLatest([
            of(stuffId),
            this.service.getState()
        ])),
        map(([stuffId, state]) => {
            if (!stuffId) {
                return state;
            }
            const specificStuff: Stuff[] = state.stuff.filter((s) => s.id === stuffId);
            return {
                stuff: specificStuff,
                tableData: this.service.getTableModel(specificStuff),
                chartData: this.service.getChartModel({stuff: specificStuff}),
                hasAssetId: true,
            };
        })
    ).subscribe(data => this.data = data);