2017-10-18 30 views
1

我目前正在调查RxJS's .merge但是我还会问这里的问题,因为我在这里找到的解释有时很棒。使用rxjs预订毁灭金字塔.subscribe with Angular - 压扁.subscribees的数量

好的,我有一个表单,根据用户输入打开一个模式窗口,我订阅模式关闭事件并传回一些数据,我会在调用/订阅服务方法以检索一些数据后使用,那么当发生这种情况时,我再次做同样的事情,然后调用/订阅另一个服务方法来更新某个日期,然后在完成后运行本地方法。所以,我在这里是3套.subscribe小号

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一起工作时,我承诺可以返回下一个服务,并链接到.then()。我真的想扁平我的代码,任何想法?

我怎么能这样做,所以我的代码不会不断缩进?

如果我没有问过或解释过我自己这么好,请说出来,然后我会转述我的问题。

回答

3

你可以做这样的事情:

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组成getUserupdateUser调用的内部可观察值。
  • 再次使用mergeMap将内部观察值合并到外部观察值中。
  • 使用do在用户更新后执行某些操作。
  • 并致电subscribe。否则,什么都不会发生。

需要注意的是,嵌套subscribe调用subscribe调用是一个反模式。

如果你愿意,你可以进一步将其压平,用在第一mergeMap结果选择添加属性:

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(); 
+0

那太好了 - 一个伟大的答案,但是很好地解释了,如果我想执行什么结果不是字符串的动作 - 例如,如果结果不是我写入控制台的字符串? –

+0

只需编写另一个observable并订阅它:'dialogRef.afterClosed()。filter(result => typeof result!=='string')。do(result => console.log(result))。subscribe()'。根据需要撰写尽可能多的文章。如果过滤器表达是互斥的,则只有一个会做某些事情。 – cartant