如何管理多个Observable调用的可见性?

时间:2017-01-19 13:34:59

标签: json angular observable

我开发了一个Angular2服务,用于从后端服务器检索列表,并计算每个类别中存在多少“链接”。 一旦我获得了每个类别的链接数量,我就会向Json对象添加一个属性来“存储”该值。

以下是代码:

nbLinks = '';

...

getCategories() {
        return this.category.find({where: {clientId: this.userApi.getCurrentId()}}).map((data) => {
                this.categoriesList = data;
                for (var i = 0; i < this.categoriesList.length; i++) {
                    var obj = this.categoriesList[i].id;
                    this.category.countLinks(obj).subscribe((linksCount) => {
                        this.nbLinks = linksCount;

                    }, err => {
                        console.log(err);
                    });
                }
                return data;
            },
            err => {
                console.log(err);
            }
        );

我使用正确的'where'子句获取json对象中的类别。 我正在循环Json以“计算”此类别中的链接数。

我的问题是在for循环之外(退出)变量i 大于我的Json长度,因此应用程序崩溃了。 我的第二个问题是我在for循环之外没有this.nbLinks的可见性。

感谢问候

1 个答案:

答案 0 :(得分:1)

我不确定我理解你的代码,但有两点突出:

1)看起来你正在混合同步和异步代码。它不起作用。

同步代码:for循环。异步代码:可观察的。

相反,您是否可以重构代码以仅使用可观察对象并链接所有操作?您可以使用Observable.from()Observable.of()

将任何数据包装在一个可观察的数据中

例如:

getCategories() {
  const categories = this.category.find({where: {clientId: this.userApi.getCurrentId()}});
  return Observable.from(categories)
           .map(category => countLinksInCategory(category));
}

如果countLinksInCategory()是异步操作,那么让该函数返回Observable,并在上面的代码中使用.mergeMap()而不是.map()

2)尽量避免在可观察的

中设置外部变量
// This part is not ideal
Obs.subscribe(linksCount => {
  this.nbLinks = linksCount;
});

我建议将getCategories()重命名为getNumLinks()以反映该功能的作用。此函数中Observable的唯一作用是生成值。然后,Observable的消费者可以使用该值(即分配,显示它......)。

就代码而言:

getNumLinks(): Observable<number> {
  // Here, count the number of links - See example code above.
  // Eventually, return an observable wrapping the final value.
}

然后,代码中的其他地方:

// This is where you assign the value returned by the Observable.
// Note that we are OUTSIDE the Observable now.
getNumLinks().subscribe(numLinks => this.nbLinks = numLinks);