0

In the code below I am trying to create an instance of PermissionService using a factory provider.

I get this error when I try to call a method on PermissionService in the class that consumes it:

Uncaught (in promise): TypeError: this.permissionService.isAdmin is not a function

What am I doing wrong?

using Angular 9.1.1

Reference: Angular Async Factory Provider

app.module.ts

providers: [
  {provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorService, multi: true },
  GlobalService,
  {provide: ErrorHandler, useClass: ClientErrorService },
  {provide: PermissionService, useFactory: async (h:HttpClient) => {
    const permissionsService = new PermissionService(h);
    await permissionsService.initialization;
    return permissionsService;
  }, deps:[HttpClient]}
  ],

PermissionService.ts

@Injectable({
  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()
  {
    const data = await ...
  }

  isAdmin() : boolean { return this._isAdmin; }
}

UsersGroupsListComponent.ts // consumes permissionService

export class UsersGroupsListComponent implements OnInit {

  IsAdmin: boolean = false;

  constructor(private globalSvc: GlobalService,
    private administrationSvc: AdministrationService,
    private userSvc: UserService,
    private permissionService: PermissionService,
    private editDialog: MatDialog) {
        this.IsAdmin = this.permissionService.isAdmin();  // Error here
  }
}

1 Answers1

1

you can't build instance of a service via async factory. the example you linked is an APP_INITIALIZER usage, which will block your app from start untill some promise is resolved. In yout example correct usage would be

export const waitForPermissionServiceInit = (serv: PermissionService) =>
  () => serv.initialization;
...
 providers: [
    PermissionService,
    {
      provide:      APP_INITIALIZER,
      useFactory:   waitForPermissionServiceInit,
      deps:         [PermissionService],
      multi:        true,
    },
  ],

so PermissionService will be constructed immediately, but app won't start, untill it is initialized

Andrei
  • 10,117
  • 13
  • 21
  • Thanks Andrei! Actually it works without PermissionService in the providers array, only the APP_INITIALIZER prover is required. –  Jul 13 '21 at 15:29
  • you have to add PermissionService to DI somehow. if it is {provideIn: 'root'} that is also fine. I didn't notice it at first overlook – Andrei Jul 13 '21 at 15:55