【问题标题】:Nested Observables and Mixed Promises嵌套 Observables 和混合 Promise
【发布时间】:2019-09-26 03:31:39
【问题描述】:

我有一个与 Firestore 后端对话的 Angular 7 应用程序。

由于异步处理,我仍在尝试围绕 Promises 与 Observables 进行比较。

考虑以下场景。在加载页面时,我需要先检查一些用户权限,然后再决定我们可以向他们展示什么。

由于权限是动态的并且本质上在页面级别,我们需要获取当前页面的 Firestore 条目,获取登录的 Firestore 用户,我单独存储的扩展用户信息,我正在寻找的权限名称,然后最后我可以检查用户的权限是否存在于页面用户权限中。

是的,我可能应该对数据进行非规范化。

但是您可以从这里看到,在显示数据之前,我必须先运行几个级别的查询,而且我真的厌倦了所有嵌套的 Observable 订阅。

  checkGroupPermission(groupId: string, permissionName: string): any {
    this.userService.getCurrentUser().then(user => {
      this.userService.getUserForFirebaseUid(user.uid).subscribe(users => {
        if (users.length === 0) { return false; }
        this.groupUsersService.getAllForUser(users[0].id).subscribe(groupUsers => {
          const groupUser = groupUsers.find(cu => cu.groupId === groupId);
          this.roleService.getRole(groupUser.roleId).subscribe(role => {
            this.rolePermissionService.getRolePermissionsForRoleId(role.id).subscribe(rolePermissions => {
              this.permissionService.getPermissionByName(permissionName).subscribe(permissions => {
                if (permissions.length === 0) { return false; }
                const rolePermission = rolePermissions.find(rp => rp.permissionId === permissions[0].id);
                if (rolePermission) {
                  return true;
                } else {
                  return false;
                }
              });
            });
          });
        });
      });
    });
  }

我还有大约五种不同的权限要检查。我想整理一下,并查看了 Promises vs Observables。

checkSomething(): Promise<boolean> {
  return this.myService.getData().then(data => {
    return true;
  }, reason => {
    return false;
  });
}

subCheckOfSomething(): Observable<boolean> {
  return this.myService.getFirebaseSubscribe().pipe(map(dataArray => {
    if (dataArray.length > 0) {
      return true;
    } else {
      return false;
    }
  }));
}

这两个函数分开很好,但如果我尝试从另一个调用一个:

checkSomething(): Promise<boolean> {
  return this.myService.getData().then(data => {
    this.subCheckOfSomething().subscribe(data => { return data; });
  }, reason => {
    return false;
  });
}

不起作用,因为 Observable 不是 Promise

我知道我可以重写 subCheckOfSomething 以返回 Promise:

subCheckOfSomething(): Promise<boolean> {
  return new Promise(resolve,reject) => {
  const data = this.myService.getFirebaseSubscribe().pipe(map(dataArray => {
    if (dataArray.length > 0) {
      return true;
    } else {
      return false;
    }
  }));
  data.subscribe(result => {
      resolve(result);
  }, err => {
      reject(err); })
  });
}

但这感觉不是最好的解决方案。有没有首选的处理方案的方法?

【问题讨论】:

    标签: angular typescript promise observable


    【解决方案1】:

    使用承诺

    RxJs 有一个toPromise-方法,你可以用它来返回一个承诺。一旦 observable 完成,promise 将解析为 observable 最后发出的值。

    subCheckOfSomething(): Promise<boolean> {
      return this.myService.getFirebaseSubscribe().pipe(map(dataArray => {
        if (dataArray.length > 0) {
          return true;
        } else {
          return false;
        }
      }))
      .toPromise();
    }
    

    使用可观察对象

    问题是你不能及早打破可观察链(你可以做一个 hack 并抛出一个错误并在最后捕获它,但我认为不推荐这样做),所以你有这些嵌套的 observable 订阅。正如您所提到的,您应该将其整理成几种方法。你也只需要在最后订阅一次,就可以像这样管理其余的方法:

      checkGroupPermission(groupId: string, permissionName: string): Observable<boolean> {
        this.userService.getCurrentUser().pipe(
          switchMap(user => {
          this.userService.getUserForFirebaseUid(user.uid).pipe(
            switchMap(users => 
              if (users.length === 0) { return of(false); }
              return this.groupUsersService.getAllForUser(users[0].id).pipe(
               switchMap(groupUsers => {
               // Basically you replace subscribe with pipe(switchMap())
            })
          })
        );
      }
    

    我个人认为在你的应用程序的某些部分有承诺是可以的。对我来说,async/await(不使用.then)似乎对我来说最易读,只要你不需要一些额外的功能,比如“中止这个检查并开始一个新的”(switchMap会很棒的)我会很好的。此外,您可以使用 toPromise (rxjs->promise) 或静态 rxjs-operator from (promise->rxjs) 轻松地将一个转移到另一个。

    【讨论】:

    • 看起来比我的干净很多。我只是想知道我是否应该始终使用 Observables?
    • 我需要对 switchMap 做一些调查。似乎是一门黑暗的艺术。然后问题来了,我需要多次调用 checkGroupPermission 并等待所有这些结果。所以我猜 checkGroupPermission 应该是一个 Observable,然后我可以为每个权限检查调用使用类似的东西。
    • switchMap 合二为一:1. 就像数组上的平面图 2. 一旦有新事件出现,现在旧的内部 observable 就会被“丢弃”
    猜你喜欢
    • 2018-02-09
    • 2019-05-19
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    • 2023-04-04
    • 1970-01-01
    • 2018-12-25
    • 2017-10-30
    相关资源
    最近更新 更多