如何在等待异步结果后构造类



在下面的代码中,我需要等待一些服务器调用来初始化缓存为类属性的对象。在研究这个问题时,我发现了几个问题,询问如何等待多个订阅。我选择的答案是使用forkJoin,如图所示。然而,我只是在路上踢罐子。现在我需要等待forkJoin。我该怎么做?我正在做的项目不是异步的,我不能去重写它

//问题2

理论上,我可以将构造函数设为私有的,并创建一个静态工厂方法——然而,我认为我又一次踢罐子了,因为我没有机制或地方等待异步工厂方法。如果我采用这种方法,我如何告诉Angular DI机制a(等待工厂方法,b(注入实例(providedIn"root"只说创建一个singleton-不允许我实际创建实例(。

export class PermissionService {
public initialization : Promise<void>;  
private _isAdmin : boolean;
private appPermissionsDict : object;
private dataPermissionsDict : object;
baseUrl = environment.baseUrl + 'permission';
constructor(private http: HttpClient) {
this.initialization = this.init();
}

async init()
{
await forkJoin([
this.getIsAdmin(),
this.getAppPermissions(),
this.getDataPermissions()
]).subscribe(([isAdmin, ap, dp]) => {
this._isAdmin = isAdmin;
this.appPermissionsDict = Object.assign({}, ...ap.map(x => x.id))
this.dataPermissionsDict = Object.assign({}, ...dp.map(x => x.id))
});

//---
// Need to wait here for properties to be set on the class
//---
}
}

使用rxjs 6.5.4/angular 9.1

您可以将每个异步调用设置为服务上的属性。

// shareReplay(1) will replay the last emission to any late subscribers
readonly isAdmin$ = this.getIsAdmin().pipe(shareReplay(1));
readonly appPermissionsDict$ = this.getAppPermissions().pipe(shareReplay(1); 
readonly dataPermissionsDict$ = this.getDataPermissions().pipe(shareReplay(1);

然后,无论您在哪里注入服务,都可以访问这些属性。在你的Angular模板中,你可以这样做:

<ng-container *ngIf="permissionService.isAdmin$ | async">
</ng-container>

模板中的这种语法将处理异步订阅,还将处理组件销毁时的取消订阅。这样,您还可以避免手动使用.subscribe编写订阅,在我看来,这要整洁得多。

我不确定在这种情况下是否需要使用forkJoin。如果你这样做,并且你需要等到你有了isAdmin$appPermissionsDict$dataPermissionsDict$的值,我会做这样的事情:

overallPermissions$ = forkJoin({
isAdmin: this.isAdmin(),
appPermissionsDict: this.getAppPermissions(),
dataPermissionsDict: this.getDataPermissions(),
})
// returns observable of { isAdmin: boolean, appPermissionsDict: object, dataPermissionsDict: object }

然后你可以在你的模板中使用这个:

<ng-container *ngIf="permissionService.overallPermissions$ | async; let overallPermissions">
<ng-container *ngIf="overallPermissions.isAdmin"></ng-container>
</ng-container>

再次重申,forkJoin将仅在所有内部可观察性发射时发射。如果在任何内部可观察器中存在错误,而您没有捕捉到它,它将默默地失败。同样,如果一个可观察值需要很长时间才能完成,那么在长期运行的值完成之前,您将无法访问其他内部可观察值。由于我所掌握的关于您的代码库的信息有限,我不会在这里使用forkJoin,每个都有单独的订阅。

我还认为在这种情况下使用providedIn: "root"没有什么问题。我想对于一个权限服务,您可能想要一个实例。

最新更新