使用rxjs .subscribe防止死角金字塔-将.subscribes的数量展平 [英] Preventing a Pyramid of Doom using rxjs .subscribe with Angular - flattening the number of .subscribes
问题描述
我目前正在研究 RxJS的.merge ,但是我会在我有时在这里找到很好的解释时,也要在这里提问.
I'm currently looking into RxJS's .merge however I'll also ask the question here as I find explanations here at times to be brilliant.
好吧,我有一个表单,该表单根据用户输入打开一个模式窗口,我订阅模式关闭事件并传回一些数据,这些数据我将在调用/订阅服务方法以检索一些数据之后使用,然后当发生这种情况时,我会再次执行相同的操作,并调用/订阅另一个服务方法以更新某个日期,然后在完成此操作后,我将运行一个本地方法.所以我这里是3个嵌套的.subscribe
s
Okay, I have a form that depending on user input opens a modal window, I subscribe to the modal close event and pass back some data that I will use after I call / subscribe to a service method to retrieve some data, then when this has happened I do the same again and call / subscribe another service method to update some date then when this has finished I run a local method. So what I have here is 3 nested .subscribe
s
const dialogRef = this.matDialog.open(ModalWindowComponent, {});
let userId = 4; // this is the real world is selected by the user
let userData = {}; // this is actually form data created by the user
// dialog is closed
dialogRef.afterClosed().subscribe((result) => {
if (typeof result === 'string') {
// subscribe to a service to get some data
this.userService.getUser(userId).subscribe((user: any) => {
// do something with the data
let mergedObj = Object.assign({}, user, {newProperty: result});
// subscribe to another service to update the data
this.scbasService.updateUser(userId, mergedObj).subscribe(() => {
this.doSomethingElse(userData);
});
});
}
});
我在这里有一个厄运金字塔".我记得在使用AngularJS并使用promises时,我可以返回下一个服务并链接了.then()
.我真的想弄平我的代码,有什么想法吗?
What I have here is a "pyramid of doom". I remember when working with AngularJS and working with promises I could return the next service and have chained .then()
s. I really want to flatten my code, any ideas?
我该怎么做,以免我的代码不断缩进?
How could I do the same here so my code doesn't indent constantly?
如果我对自己的问询或解释得还不够好,请这么说,我将重述我的问题.
If I haven't asked or explained myself so well please say so and I will rephrase my question.
推荐答案
您可以执行以下操作:
dialogRef
.afterClosed()
.filter(result => typeof result === 'string')
.mergeMap(result => this.userService
.getUser(userId)
.mergeMap(user => {
let mergedObj = Object.assign({}, user, { newProperty: result });
return this.scbasService.updateUser(userId, mergedObj);
})
)
.do(() => this.doSomethingElse(userData))
.subscribe();
- 使用
filter
,以便仅处理string
结果. - 使用
mergeMap
可以为getUser
和updateUser
调用组成一个内部可观察对象. - 再次使用
mergeMap
将内部可观测值合并到外部可观测值. - 更新用户后,使用
do
进行操作. - 然后调用
subscribe
.否则,什么都不会发生. - Use
filter
so that onlystring
results are processed. - Use
mergeMap
to compose an inner observable for thegetUser
andupdateUser
calls. - Use
mergeMap
again to merge the inner observable into the outer observable. - Use
do
to do something after the user is updated. - And call
subscribe
. Otherwise, nothing will happen.
需要记住的是,在subscribe
调用中嵌套subscribe
调用是一种反模式.
Something to keep in mind is that nesting subscribe
calls within subscribe
calls is an antipattern.
如果需要,可以使用第一个mergeMap
中的结果选择器将其进一步展平,以添加属性:
If you want, you could flatten it further, using the result selector in the first mergeMap
to add the property:
dialogRef
.afterClosed()
.filter(result => typeof result === 'string')
.mergeMap(
result => this.userService.getUser(userId),
(result, user) => Object.assign({}, user, { newProperty: result })
)
.mergeMap(
userWithNewProperty => this.scbasService.updateUser(userId, userWithNewProperty)
)
.do(() => this.doSomethingElse(userData))
.subscribe();
这篇关于使用rxjs .subscribe防止死角金字塔-将.subscribes的数量展平的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!