使用rxjs .subscribe防止死角金字塔-将.subscribes的数量展平 [英] Preventing a Pyramid of Doom using rxjs .subscribe with Angular - flattening the number of .subscribes

查看:133
本文介绍了使用rxjs .subscribe防止死角金字塔-将.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 .subscribes

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可以为getUserupdateUser调用组成一个内部可观察对象.
  • 再次使用mergeMap将内部可观测值合并到外部可观测值.
  • 更新用户后,使用do进行操作.
  • 然后调用subscribe.否则,什么都不会发生.
    • Use filter so that only string results are processed.
    • Use mergeMap to compose an inner observable for the getUser and updateUser 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆