我有一个标头组件,该组件进行调用以获取用户令牌并存储用户数据。然后,我有一个不同的组件(管理组件),它不是标头的子代,它依赖于用户数据来获取其他数据。我遇到的问题是管理组件在标头组件完成对用户的调用之前初始化,因此破坏了我的管理组件。换句话说,由于标题尚未设置活动公司,因此代码执行中断。有没有办法确保这些内容在Angular 6中同步加载,以便我可以避免此问题?
header.component.ts
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../../services/auth.service';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
user: any;
activeCompany: any;
constructor(private authService: AuthService) { }
ngOnInit() {
this.authService.getToken().then((user) => {
this.user = user;
this.user.Companies = JSON.parse(this.user.Companies.split('"').join('"'));
this.authService.getActiveCompany$().subscribe((company: any) => {
if(!company) {
let company = this.user.Companies[0]
this.authService.setActiveCompany$(JSON.stringify(company));
}
this.activeCompany = company;
});
});
}
setActiveCompany(company) {
this.authService.setActiveCompany$(company)
}
}
admin.component.ts
import { Component, OnInit } from '@angular/core';
import { TagService } from '../../services/tag.service';
import { AuthService } from '../../services/auth.service';
@Component({
selector: 'app-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.css']
})
export class AdminComponent implements OnInit {
companyId: number;
tags: any;
loading: boolean = true;
constructor(
private tagService: TagService,
private authService: AuthService
) {}
ngOnInit() {
this.authService.getActiveCompany$().subscribe((company: any) => {
// The line below breaks because the active company has not been set yet by the header
this.companyId = company.Id
this.tagService.getTags(companyId).then((tags) => {
this.setTags(tags)
this.loading = false;
});
});
}
}
auth.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, Subject, BehaviorSubject } from 'rxjs';
import { AppConfig } from '../../app-config';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private activeCompany$: Subject<any>;
constructor(private http: HttpClient, private _config: AppConfig) {
let initialActiveCompany;
if (window.localStorage.getItem('activeCompany')) {
initialActiveCompany = JSON.parse(window.localStorage.getItem('activeCompany'));
} else {
this.getToken().then((user: any) => {
initialActiveCompany = user.Companies = JSON.parse(user.Companies.split('"').join('"'))[0];
});
}
this.activeCompany$ = new BehaviorSubject<any>(initialActiveCompany);
}
getToken() {
return new Promise(resolve => {
this.http.get(`${this._config.API_URL}/Token`).subscribe(data => {
resolve(data);},
err => {
console.log("Error retrieving token", err);
});
});
}
// Returns the observable (read-only) part of this subject
getActiveCompany$(): Observable<any> {
return this.activeCompany$.asObservable();
}
// Stores the new company value in local storage and pushes it to the subject
setActiveCompany$(company: any) {
window.localStorage.setItem('activeCompany', JSON.stringify(company));
this.activeCompany$.next(company);
}
}
答案 0 :(得分:5)
我认为您应该多组织一些服务来处理异步性。
您应该在AuthService中将activeCompany
设置为BehaviorSubject
,然后在admin中订阅更改。
因为更改getTags()
时需要调用activeCompany
。
答案 1 :(得分:3)
我建议您在管理组件中使用解析器服务。首先在cli中使用 ng g s resolver 命令创建一个新的解析器服务,然后使用此代码
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { AuthService } from '../../services/auth.service';
import {
Resolve,
ActivatedRouteSnapshot,
RouterStateSnapshot
} from "@angular/router";
@Injectable({
providedIn: "root"
})
export class ResolverService implements Resolve<any> {
this.companyId: any;
constructor(private authService: AuthService) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> {
return this.authService.getActiveCompany$().subscribe((company: any) => {
this.companyId = company.Id
this.tagService.getTags(companyId).then((tags) => {
this.setTags(tags)
this.loading = false;
});
});
}
}
,然后将其添加到管理组件下的路由模块中
{
path: "admin",
component: AdminComponent,
resolve: {
result: ResolverService
}
}
,然后最后在您的管理组件中导入 ActicatedRoute
import { ActivatedRoute } from "@angular/router";
并添加到您的构造函数中
userData = null // store the data you want from your authService here from your resolver
constructor(private actr: ActivatedRoute) {
this.actr.data.pipe(map(data => data.resuslt)).subscribe(res => {
this.userData = res;
});
}
我没有时间阅读您的authservice.ts,但我希望您能理解
答案 2 :(得分:0)
您是否尝试实施安全导航操作员?进行一些重组,就可以得到等待结果到达以实际呈现值的结果。
The current hero's name is {{currentHero?.name}}
您可以看到docs here。
答案 3 :(得分:0)
*ngIf
,则使用true
加载管理组件。