Как получить сервисный ответ перед загрузкой компонента 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*/
Другие вопросы по тегам