【问题标题】:How to solve time raise problems in Angular?如何解决 Angular 中的时间引发问题?
【发布时间】:2018-07-11 06:53:27
【问题描述】:

我正在编写一个 Angular 服务来证明用户权限。在构造函数中,我想从 API 获取当前登录的用户。创建的当前用户用于本服务的其他方法。从组件调用此方法以检查可以显示哪些内容等。 问题是服务中的方法被调用的速度比当前用户可用的速度快。 有没有办法解决这个问题?

permission.service.ts

@Injectable()
export class PermissionService {
  currUser = {
    'id': "",
    'permission': ""
  };
  apiService: AlfrescoApiService;
  authService: AuthenticationService;

  constructor(apiService: AlfrescoApiService, authService: AuthenticationService) {
    this.apiService = apiService;
    this.authService = authService;

    this.init();
  }

  init() {
    let userId: string = this.authService.getEcmUsername();    
    this.currUser.id = userId;

//API call
    this.apiService.sitesApi.getSiteMember(SITENAME, userId).then(resp => {
      this.currUser.permission = resp.entry.role;
    })
  }

  isSiteManager(): boolean {
    console.log(this.currUser.permission, this.currUser);
    if(this.currUser.permission === "SiteManager"){
      return true;
    }else{
      return false;
    }
  }
}

方法调用

export class AppLayoutComponent {

  constructor(permissionService:PermissionService) {
    permissionService.isSiteManager();
  }

}

在谷歌浏览器中输出

{id:“管理员”,权限:“”}
id:“admin”权限:“SiteManager”

【问题讨论】:

  • the methods in the service are called faster than the current user is available - 您要查找的词是 asynchry ...即this.currUser.permission = resp.entry.role; 是异步执行的,但您的代码表明您不知道这一点
  • 是的,我知道它是异步的。但是我不知道如何解决这个问题。
  • 这取决于你如何使用isSiteManager() 的结果以及应用程序是否使用Angular Router。

标签: javascript angular typescript asynchronous promise


【解决方案1】:

你应该在你的 getEcmUsername() 中使用 promise 来处理这个;之后你可以像这样编写代码
`

this.authService.getEcmUsername().then((userID) => {
    this.apiService.sitesApi.getSiteMember(SITENAME, userId).then(resp => {
      this.currUser.permission = resp.entry.role;
    })
});

`

【讨论】:

  • 谢谢,但这不起作用。 "getEcmUsername()" 返回一个字符串。
  • 您可以在 getEcmUsername 方法中使用return Promise.resolve(string)
  • 这可能会对你有所帮助 [stackoverflow.com/a/45090069/7235892] 只需将你的 init 函数包装在 promise 中或使用 async/await
【解决方案2】:

在我看来,更好的解决方案是在这里使用 Observable 和 rxjs。在服务中,您可以创建主题并在您的组件中订阅它,以确保数据已经存在。例如:

@Injectable()
export class PermissionService {
 public Subject<bool> userFetched= new Subject<bool>();
  currUser: IUser = {
    'id': "",
    'permission': ""
  };
  apiService: AlfrescoApiService;
  authService: AuthenticationService;

  constructor(apiService: AlfrescoApiService, authService: AuthenticationService) {
    this.apiService = apiService;
    this.authService = authService;

    this.init();
  }

  init() {
    let userId: string = this.authService.getEcmUsername();    
    this.currUser.id = userId;

//API call
    this.apiService.sitesApi.getSiteMember(SITENAME, userId).subscribe((data:IUser)=> 
  {
    this.user=data;
   this.userFetched.next(true);
  })
 }

  isSiteManager(): boolean {
    console.log(this.currUser.permission, this.currUser);
    if(this.currUser.permission === "SiteManager"){
      return true;
    }else{
      return false;
    }
  }
}

之后在你的组件中:

export class AppLayoutComponent {

  constructor(permissionService:PermissionService) {
    permissionService.userFetched.subscribe((data)=>{
     permissionService.isSiteManager();
  });
  }
}

这是更好的方法。您需要考虑是 Subject 还是 BehaviourSubject 更好。

【讨论】:

    【解决方案3】:

    感谢所有回答的人。我找到了解决方案。我已将isSiteManager() 方法更改为检查所有四种权限类型的方法。此方法在then() 块中执行,并影响每个权限类型的四个变量。我可以从其他组件中获取这些变量。 看起来像这样:

     @Injectable()
    export class PermissionService {
      isSiteManager: boolean;
      isSiteConsumer: boolean;
      isSiteContributor: boolean;
      isSiteCollaborator: boolean;
      userId : string;
    
      constructor(private apiService: AlfrescoApiService, private authService: AuthenticationService) {
        this.init();
      }
    
      init() {
        this.isSiteCollaborator = false;
        this.isSiteConsumer = false;
        this.isSiteContributor = false;
        this.isSiteManager = false;
        this.userId = localStorage.USER_PROFILE;
    
        //proof permission of user
        this.apiService.sitesApi.getSiteMember(SITENAME, this.userId).then(resp=>{
          if(resp.entry.role === "SiteManager"){
            this.isSiteManager = true;
          }else if(resp.entry.role === "SiteConsumer"){
            this.isSiteConsumer = true;
          }else if(resp.entry.role === "SiteContributor"){
            this.isSiteContributor = true;
          }else{
            this.isSiteCollaborator = true;
          }
        });
      }
    }
    

    现在我可以像这样询问其他组件中的变量:

    export class AppLayoutComponent {
    
      constructor(private permissionService : PermissionService) {
        if(permissionService.isSiteManager){
          console.log("You are Boss!");
        }
      }
    }
    

    【讨论】:

      【解决方案4】:

      您应该调用您的服务方法同步。为此,您必须映射来自服务的响应:

      您的组件代码:

      constructor() {
      ...
      permissionService.isSiteManager().map(
      response => {
          isManager = response;
      }
      );
      }
      

      类似的东西。

      调用map operator之前导入:

      import 'rxjs/add/operator/map';
      

      【讨论】:

      • 使用.subscribe()
      • @kvetis 你错了,订阅是异步的。作者需要同步调用
      • isSiteManager 不返回可观察值。如果会:您的答案如何解决问题?
      • 我认为你需要重新学习 Observables。 .map.subscribe 都是异步的。我也同意@abetteroliver,即使你使用.subscribe OP 也需要重写isSiteManager
      猜你喜欢
      • 2021-09-06
      • 1970-01-01
      • 2021-06-27
      • 1970-01-01
      • 2023-01-24
      • 1970-01-01
      • 2021-01-14
      • 2021-11-09
      • 1970-01-01
      相关资源
      最近更新 更多