Angular 如何使用服务初始化可注入变量

Angular 如何使用服务初始化可注入变量,angular,asynchronous,promise,ionic2,injectable,Angular,Asynchronous,Promise,Ionic2,Injectable,当用户登录时,我使用Ionic2存储来存储用户访问令牌凭据 当用户尝试访问后端api时,我需要向REST客户端提供访问令牌 我已经使用 最初,包使用 export class CategoryService extends RESTClient{ categoryList : Category[] = []; public user:User; constructor(protected http:Http) {super(http)} } 我曾经将UserStorag

当用户登录时,我使用Ionic2存储来存储用户访问令牌凭据

当用户尝试访问后端api时,我需要向REST客户端提供访问令牌

我已经使用 最初,包使用

export class CategoryService extends RESTClient{
    categoryList : Category[] = [];
    public user:User;
    constructor(protected http:Http) {super(http)}
}
我曾经将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;
 }
添加访问令牌凭据的步骤

现在,我在我的页面组件中的调用必须如下所示:

@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类的构造函数中设置用户。因此,我必须首先从存储中获取用户,在category服务中使用“setter”,然后将getAvailableCategories()调用嵌套在getUser()中。然后()函数

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

我知道这是因为调用是异步的,但我觉得使用setTimeout之类的东西来“等待”getUser调用返回是有问题的,不是100%可靠的

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

this.categoryService.getAvailableCategories().then()
并从那里继续,无需嵌套的承诺调用


我准备进行任何明智的更改,以使访问令牌立即可用。

如果
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) },
        () => { }
    );
}

请注意,它是异步的,然后等待它。userStorage.getUser()
然后(…)
表示异步。这可能只是时间问题。访问该值时,该值尚不可用。当值变为可用时,您需要正确地链接所有异步调用以获得“通知”(您传递的回调被调用)。您能再显示一点代码吗?页面组件是什么样子的?@MichałMiszczyszyn我将整个组件添加到了问题中。我喜欢这个想法,它解决了我的嵌套挑剔,但我正在寻找在CategoryService中使用的东西,所以我不必调用CategoryService.setUser()。我想帮助您找到一个解决方案,以便在Angular加载页面时,CategoryServices的用户变量将在后台准备就绪。@Schwoebel在纯TypeScript/JavaScript中完全可以做到这一点。只是hBoylan的ng2http包decorators显然不允许异步参数。您应该在GitHub上打开一个问题。@Schwoebel我的回答对您有任何帮助吗?
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) },
        () => { }
    );
}