Как получить сервисный ответ перед загрузкой компонента Angular 4?
У меня есть сервис, который делает запрос к API, и в соответствии с его ответом я должен решить, должен ли компонент быть загружен или нет. но из-за времени, потраченного на получение ответа, компонент загружается независимо от состояния ответа, и через некоторое время (около 0,5 с) ответ получен, и если компонент не должен быть загружен, мы переходим в другое место. Я не хочу, чтобы компонент загружался до получения ответа.
Я использую функцию canActivate от AuthGuard в Angular 4, как показано ниже:
export class AuthGuard implements CanActivate {
access = true;
res: any;
constructor(private router: Router, private routeService: RouteService){}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
setTimeout(() => {
if( !this.exept.includes(this.router.url) ){
this.routeService.FormOperation(this.router.url).subscribe(item=> {
this.res = item;
if (this.res.status == 200) {
if (this.res.data.Access[1] == false) {
this.access = false;
}
if (this.access == true)
{
return true;
}
else {
this.router.navigate(['/dashboard']);
return false;
}
})
}
},0);
if (sessionStorage.getItem('token') && this.access)
{
// logged in so return true
return true;
}
// not logged in so redirect to login page with the return url
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
return false;
}
Я использую setTimeout, чтобы я мог получить правильный this.router.url.
Обновить:
Я добавил резольвер, как показано ниже:
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): void {
this.routeService.FormOperation(this.router.url).toPromise()
.then(response => {
this.form_operation_data = response;
if(!this.form_operation_data['data']['Access'][1]) {
this.router.navigate(['/dashboard']);
}
})
.catch(err => {
console.error(err);
});
}
но все же компонент загружается до получения данных ответа...
1 ответ
Вы так близко: ваш AuthGuard должен вернуться true
или же false
и на основании этого значения будет активирован маршрут или нет. Теперь вы должны добавить эту аутентификацию в вашу маршрутизацию (вот пример для активации дочернего маршрута). А если вы хотите получить данные перед загрузкой компонента, вы можете использовать средства распознавания.
Резольвер
/* Imports */
@Injectable()
export class DataResolverService {
constructor(
private _serviceToShareData: ServiceToShareData,
private _serviceToGetData: ServiceToGetData,
) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): void {
this._serviceToGetData.anyRequestToApi()
.then(response => {
this._serviceToShareData.setData(response);
})
.catch(err => {
console.error(err);
});
}
}
И теперь вы можете получить извлеченные данные из службы ServiceToShareData в вашем компоненте, который вы хотите загрузить с этими данными.
Модуль маршрутизации
/* Other imports */
import {DataResolverService } from './path-to-service/data-resolver-service'
import {AuthGuard} from './path-to-service/auth-guard'
const routes: Routes = [
{
path: 'app',
component: ParentComponent,
children: [
{
path: 'child-route',
component: childRouteComponent,
canActivate: [AuthGuard],
resolve: {
data: DataResolverService
}
}
]
}
];
/* Other stuff like @NgModule and class export*/