如何避免嵌套订阅超过两个级别
Posted
技术标签:
【中文标题】如何避免嵌套订阅超过两个级别【英文标题】:how to avoid nested subscribe more than two levels 【发布时间】:2019-09-07 15:53:48 【问题描述】:我有四个相互依赖的订阅。我知道关于避免嵌套订阅的答案太多了。但是没有人回答超过两个级别。
如何避免这么多的嵌套订阅
这是我的组件代码
if (this.code)
this.appService.updateData('Users/clever_token', code: this.code).subscribe(data =>
if (data.detail)
this.accessToken = data.detail.access_token;
this.appService.getCleverData('/v2.1/me', this.accessToken).subscribe(data1 =>
if (data1.links)
this.userData.user_type = data1.type;
this.appService.getCleverData(data1.links[1].uri, this.accessToken).subscribe(data2 =>
if (data2.data)
this.userData.name = data2.data.name.first + ' ' + data2.data.name.last;
this.userData.clever_id = data2.data.id;
this.userData.email = data2.data.email;
this.appService.updateData('Users/cleaver_login', this.userData).subscribe(data3 =>
if (data3.detail)
console.log(data3.detail);
);
);
);
);
这是服务代码
getCleverData(url, token)
let reqHeader = new HttpHeaders(
'Authorization': 'Bearer ' + token
)
return this.http.get(API_PREFIX + url, headers: reqHeader )
.pipe(
map((data: any) =>
console.log(data);
if (data) return data;
),
catchError(this.handleError)
);
/** PUT: update a data to the server */
updateData (url, data?)
let httpParams = new HttpParams();
Object.keys(data).forEach(function (key)
httpParams = httpParams.append(key, data[key]);
);
return this.http.post(this.apiUrl + url, httpParams, httpOptions)
.pipe(
map((data: any) =>
if (data.status == 0)
this.presentToast(data.message);
if (data) return data;
),
catchError(this.handleError)
);
有什么办法可以避免这么多订阅。我无法删除其中的任何内容,因为其中一些来自我们的服务器,而另一些则是第三方
【问题讨论】:
看看 rxjs 操作符(mergeMap、zip、forkJoin) 看看forkJoin:***.com/questions/43166214/…,这个例子只有2个http请求,但是你可以添加更多的请求。 我试过了。但是有一个只有两个级别的示例,我不能使用 forkJoin,因为所有 API 请求都相互依赖。我不能把他们叫在一起 所以你需要 flatMap:***.com/questions/44593900/…。显然,您必须在发送数据之前更改数据,但至少您没有嵌套的观察者 你不会嵌套订阅,也不是一层 【参考方案1】:有几个选项,但我认为您需要该结构,因为您需要来自上一个 observable 的数据,因此您可以使用 filter()
和 switchMap()
。
filter()
能够过滤掉不包含必要值的值switchMap()
- 以切换到新流。
更新:
你的代码有一个重构版本:
if (!this.code)
return;
this.appService.updateData('Users/clever_token', code: this.code).pipe(
filter(data => !!data.detail),
switchMap(data =>
this.accessToken = data.detail.access_token;
return this.appService.getCleverData('/v2.1/me', this.accessToken);
),
filter(data1 => !!data1.links),
switchMap(data1 =>
this.userData.user_type = data1.type;
return this.appService.getCleverData(data1.links[1].uri, this.accessToken);
),
filter(data2 => !!data2.data),
switchMap(data1 =>
this.userData.name = data2.data.name.first + ' ' + data2.data.name.last;
this.userData.clever_id = data2.data.id;
this.userData.email = data2.data.email;
return this.appService.updateData('Users/cleaver_login', this.userData);
),
).subscribe(data3 =>
if (data3.detail)
console.log(data3.detail);
【讨论】:
您能创建一个至少 3 个级别的示例,以便我更好地理解它吗?以上是关于如何避免嵌套订阅超过两个级别的主要内容,如果未能解决你的问题,请参考以下文章
Rails 3 - 嵌套资源和多态路径:可以到两个级别,但在三个级别中断