Angular2:嵌套订阅与循环内的第二个订阅
Angular2: Nested subscribe with second subscribe inside the loop
我刚接触 Angular2 一周!
基本上有2个API调用。
- 第一个 API 调用为我提供了 json 个对象的数组 (queryResults)。 (第 1 次订阅)
- 在视图中显示该数组。
- 遍历 (queryResults) 数组并从每个数组元素 (queryResults[i].oldLastSeen) 中选择一个特定的键值对。
- 将该值 (oldLastSeen) 作为请求参数传递给另一个 API,它会给我一个字符串 (newLastSeen)。 (第二次订阅)
- 用queryResult中的newLastSeen替换oldLastSeen
由于 Observable 的异步性质,问题出现在第 5 步。我无法在内部订阅中访问 queryResults[i].oldLastSeen
并且基本上是未定义的。因此 lastSeen 不会更新。
开始调用 getLastSeen()
,
代码如下所示:
temp: any[];
rows: any[];
getLastSeen() {
this._someService.getQueryResults(this.query)
.subscribe(queryResults => {
this.rows = queryResults;
this.updateLastSeen(this.rows);
});
}
private updateLastSeen(rows) {
this.temp = rows; //temp: any[];
for(var i=0; i<this.temp.length; i++) {
if(this.temp[i].id != null || this.temp[i].oldLastSeen != null) {
//Some operations here
this._someService.getNewLastSeen(this.temp[i].oldLastSeen)
.subscribe(
newLastSeen => {
this.rows[i].oldLastSeen = newLastSeen; //This doesnot happen!
},
error => alert(error),
() => console.log("Finished.")
);
}
}
}
两天以来一直在敲我的头,遇到了 flatMap、switchMap 等。但对它们的用法非常怀疑。
更新:工作代码:
我听取了 Bryan 的反馈,并对他建议的代码进行了一些修改。这是对我有用的:
this._someService.getQueryResults(this.query)
.do(qr => {this.rows = qr;})
.flatMap(queryResults => Observable.from(queryResults))
.filter(queryItem => queryItem["id"] != null || queryItem["oldLastSeen"] != undefined)
.do(queryItem => { // did some operations/ manipulations here})
.mergeMap(queryItem => this._someService.getNewLastSeen(this.queryItem["oldLastSeen]),
(queryItem, newLastSeen) => [queryItem, newLastSeen])
.subscribe(([queryItem, newLastSeen]) => {
queryItem.oldLastSeen = newLastSeen
});
一般来说,如果您有嵌套订阅,那么您正在处理一个可以改进的反模式。我还没有找到一个令人信服的案例来使用它。我不确定对 flatMap 或 switchMap 持怀疑态度意味着什么,但它们是非常有用的运算符,尤其是 switchMap。如果你的工具包中没有 switchMap,你将无法做超出 rxjs 基础知识的事情。
getLastSeen() {
this._someService.getQueryResults(this.query)
.do(qr => this.rows = qr;)
.flatMap(queryResults => Observable.from(queryResults))
.filter(queryItem => queryItem.id !== null || queryItem.oldLastSeen !== null)
// you can insert a map or do operator here to accomplish the operations you mention, depending on what they are, or you can possibly just do them inside switchMap
.switchMap(queryItem => this._someService.getNewLastSeen(queryItem.oldLastSeen),
(queryItem, newLastSeen) => [queryItem, newLastSeen])
.subscribe(([queryItem, newLastSeen]) => queryItem.oldLastSeen = newLastSeen);
}
一块一块地看:
你得到你的查询
您将结果设置到视图中。功能纯粹主义者会说在这里这样做是不好的做法,因为它会产生副作用,但无论如何。我不是纯粹主义者。
这很棘手,但您正在将结果扁平化为可观察的数据流。您从结果数组创建一个可观察对象,然后 flatmap 一个一个地发出它们,您也可以在这里使用 .mergeAll() 。这是一种更具反应性的循环结果方式。
过滤掉您不感兴趣的项目
你的 "operations" 的占位符行,也许是映射或做,在不知道想要的效果的情况下很难说。也可能只是在 switchMap 中可行,但要注意样式和保持运算符简洁。
switchMap 进入新的 observable,switchMap 将订阅内部 observable 并发出结果,关键是 switchMap 的第二个参数,它允许您将内部和内部的项目组合起来外部可观察的。在这里我们只是将它们放入一个数组并发出两个值的数组
重置订阅中的项目。这里唯一有趣的是使用打字稿语法,让您可以命名数组中的项目,因为您知道您正在获得一个包含 2 个项目的数组。
我刚接触 Angular2 一周!
基本上有2个API调用。
- 第一个 API 调用为我提供了 json 个对象的数组 (queryResults)。 (第 1 次订阅)
- 在视图中显示该数组。
- 遍历 (queryResults) 数组并从每个数组元素 (queryResults[i].oldLastSeen) 中选择一个特定的键值对。
- 将该值 (oldLastSeen) 作为请求参数传递给另一个 API,它会给我一个字符串 (newLastSeen)。 (第二次订阅)
- 用queryResult中的newLastSeen替换oldLastSeen
由于 Observable 的异步性质,问题出现在第 5 步。我无法在内部订阅中访问 queryResults[i].oldLastSeen
并且基本上是未定义的。因此 lastSeen 不会更新。
开始调用 getLastSeen()
,
代码如下所示:
temp: any[];
rows: any[];
getLastSeen() {
this._someService.getQueryResults(this.query)
.subscribe(queryResults => {
this.rows = queryResults;
this.updateLastSeen(this.rows);
});
}
private updateLastSeen(rows) {
this.temp = rows; //temp: any[];
for(var i=0; i<this.temp.length; i++) {
if(this.temp[i].id != null || this.temp[i].oldLastSeen != null) {
//Some operations here
this._someService.getNewLastSeen(this.temp[i].oldLastSeen)
.subscribe(
newLastSeen => {
this.rows[i].oldLastSeen = newLastSeen; //This doesnot happen!
},
error => alert(error),
() => console.log("Finished.")
);
}
}
}
两天以来一直在敲我的头,遇到了 flatMap、switchMap 等。但对它们的用法非常怀疑。
更新:工作代码:
我听取了 Bryan 的反馈,并对他建议的代码进行了一些修改。这是对我有用的:
this._someService.getQueryResults(this.query)
.do(qr => {this.rows = qr;})
.flatMap(queryResults => Observable.from(queryResults))
.filter(queryItem => queryItem["id"] != null || queryItem["oldLastSeen"] != undefined)
.do(queryItem => { // did some operations/ manipulations here})
.mergeMap(queryItem => this._someService.getNewLastSeen(this.queryItem["oldLastSeen]),
(queryItem, newLastSeen) => [queryItem, newLastSeen])
.subscribe(([queryItem, newLastSeen]) => {
queryItem.oldLastSeen = newLastSeen
});
一般来说,如果您有嵌套订阅,那么您正在处理一个可以改进的反模式。我还没有找到一个令人信服的案例来使用它。我不确定对 flatMap 或 switchMap 持怀疑态度意味着什么,但它们是非常有用的运算符,尤其是 switchMap。如果你的工具包中没有 switchMap,你将无法做超出 rxjs 基础知识的事情。
getLastSeen() {
this._someService.getQueryResults(this.query)
.do(qr => this.rows = qr;)
.flatMap(queryResults => Observable.from(queryResults))
.filter(queryItem => queryItem.id !== null || queryItem.oldLastSeen !== null)
// you can insert a map or do operator here to accomplish the operations you mention, depending on what they are, or you can possibly just do them inside switchMap
.switchMap(queryItem => this._someService.getNewLastSeen(queryItem.oldLastSeen),
(queryItem, newLastSeen) => [queryItem, newLastSeen])
.subscribe(([queryItem, newLastSeen]) => queryItem.oldLastSeen = newLastSeen);
}
一块一块地看:
你得到你的查询
您将结果设置到视图中。功能纯粹主义者会说在这里这样做是不好的做法,因为它会产生副作用,但无论如何。我不是纯粹主义者。
这很棘手,但您正在将结果扁平化为可观察的数据流。您从结果数组创建一个可观察对象,然后 flatmap 一个一个地发出它们,您也可以在这里使用 .mergeAll() 。这是一种更具反应性的循环结果方式。
过滤掉您不感兴趣的项目
你的 "operations" 的占位符行,也许是映射或做,在不知道想要的效果的情况下很难说。也可能只是在 switchMap 中可行,但要注意样式和保持运算符简洁。
switchMap 进入新的 observable,switchMap 将订阅内部 observable 并发出结果,关键是 switchMap 的第二个参数,它允许您将内部和内部的项目组合起来外部可观察的。在这里我们只是将它们放入一个数组并发出两个值的数组
重置订阅中的项目。这里唯一有趣的是使用打字稿语法,让您可以命名数组中的项目,因为您知道您正在获得一个包含 2 个项目的数组。