【问题标题】:How do I Initialize Injectable variable using a service如何使用服务初始化 Injectable 变量
【发布时间】:2017-02-13 19:16:41
【问题描述】:

当用户登录时,我正在使用 Ionic2 Storage 存储用户 access_token 凭据。

当用户尝试访问后端 api 时,我需要将 access_token 提供给 REST 客户端。

我使用hBoylan's ng2-http package 创建了服务 最初该包使用

export class CategoryService extends RESTClient{
    categoryList : Category[] = [];
    public user:User;
    constructor(protected http:Http) {super(http)}
}

我已经使用Angular2 DI在构造函数中添加了一个UserStorage组件:

let categoryServiceFactory = (http:Http, userStorage:UserStorage) => {
    return new CategoryService(http, userStorage);
}
export let categoryServiceProvider = 
{
    provide: CategoryService,
    useFactory: categoryServiceFactory,
    deps: [Http, UserStorage]
}

得到这个:

export class CategoryService extends RESTClient{
  categoryList : Category[] = [];
  public user:User;
  constructor(protected http: Http, protected userStorage: UserStorage)
{
  super(http);
  this.userStorage.getUser().then((data:User) => {this.user = data})
}

目前当我打电话时

 @GET('/itemtype/list')
 @Produces<String>()
 public getAvailableCategories(): Observable<String> {
   return null;
 }

我需要使用

 protected requestInterceptor(req: Request) {
   req.headers.set('Authorization', `Bearer ${this.user.api_credentials.access_token}`)
    return req;
 }

添加 access_token 凭证

截至目前,我在页面组件中的调用必须如下所示:

@Component({
  selector: 'page-categories',
  templateUrl: 'categories.html',
  providers: [User]
})
export class CategoriesPage implements OnInit {
  // list of categories
  public categories: any;

constructor(public nav: NavController,
public categoryService: CategoryService,
public userStorage: UserStorage,
public user: User) {}

ngOnInit() {
  this.userStorage.getUser().then((user: User) => {
    this.user = user
    this.categoryService.setUser(this.user);
    this.categoryService.getAvailableCategories().subscribe(
      (data) => { console.log(data) },
      error => console.log(error),
      () => { });
  });
}

// view category
viewCategory(categoryId) {
  this.nav.push(CategoryPage, { id: categoryId });
}

showChildren(category: Category) {
  category.open = !category.open;
}

openCategoryPage($event, category: Category) {
  $event.stopPropagation();
  this.nav.push(CategoryPage, { cat_id: category.id })
}

}

看起来像这样的原因是因为我似乎无法在 CategoryService 类的构造函数中设置用户。所以我必须首先从存储中获取用户,在类别服务中使用“setter”,然后将 getAvailableCategories() 调用嵌套在 getUser().then() 函数中。

这是因为在 CategoryService 构造函数完成从 UserStorage 设置用户之前调用了 getCategories 函数。

我知道这是因为调用是异步的,但我觉得使用 setTimeout 之类的东西来“等待”直到 getUser 调用返回是很麻烦的,而且不是 100% 可靠的。

还有什么我可以尝试的吗?我真的很想打电话给

this.categoryService.getAvailableCategories().then()

并在没有嵌套的 Promise 调用的情况下从那里继续。

我愿意进行任何精明的更改,以使 access_token 立即可用。

【问题讨论】:

  • then(...) 表示异步。这可能只是一个时间问题。访问时该值尚不可用。当值可用时,您需要正确链接所有异步调用以获得“通知”(您传递的回调被调用)。
  • 你能显示更多的代码吗?页面组件长什么样子?
  • @MichałMiszczyszyn 我将整个组件添加到问题中。

标签: angular asynchronous promise ionic2 injectable


【解决方案1】:

如果getUser 调用是异步的,您可以尝试使其同步:)

如果这不是你的选择,有一个语法糖可以帮助你以更好的方式处理异步调用 – async/await:

async ngOnInit() {
    this.categories = this.categoryService.getCategories();
    this.user = await this.userStorage.getUser();
    this.categoryService.setUser(this.user);
    this.categoryService.getAvailableCategories().subscribe(
        (data) => { console.log(data) },
        (error) => { console.log(error) },
        () => { }
    );
}

注意是async ngOnInit,然后是await this.userStorage.getUser()

【讨论】:

  • 我喜欢这个想法,它解决了我的嵌套挑剔问题,但我正在寻找可以在 CategoryService 中使用的东西,因此我不必调用 categoryService.setUser()。我希望帮助找出一个解决方案,以便在 Angular 加载页面时,CategoryServices 的用户变量将在后台准备好。
  • @Schwoebel 在纯 TypeScript/JavaScript 中完全可以做到这一点。只是hBoylan's ng2-http package 装饰器显然不允许异步参数。你应该在 GitHub 上打开一个问题。
  • @Schwoebel 我的回答对您有任何帮助吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-07
  • 2012-10-11
  • 1970-01-01
相关资源
最近更新 更多