Компонент визуализируется до завершения NgOnInit?

У меня есть компонент, который выполняет некоторые вызовы службы, которая вызывает API. Компонент отрисовывается до завершения этих вызовов, что приводит к пустой странице.

Это код из компонента:

import {Component, OnInit, OnDestroy} from '@angular/core';
import {AuthService} from '../services/auth.service';
import {AssignmentService} from '../services/assignment.service';
import {Assignment} from '../models/Assignment';
import {Request} from '../models/Request';
import {MeService} from '../services/me.service';
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';
import {Router} from '@angular/router';
import {NavbarService} from '../services/navbar.service';

@Component({
  selector: 'app-newrequest',
  templateUrl: './newrequest.component.html',
  providers: [AssignmentService]
})
export class NewrequestComponent implements OnInit {
  me: MicrosoftGraph.User;
  assignments: Assignment[];
  requests: Request[] = [];
  ready = false;

  constructor(private meService: MeService,
              private authService: AuthService,
              private assignmentService: AssignmentService,
              private router: Router,
              public nav: NavbarService) {
  }

  ngOnInit() {
    this.nav.show();
    this.nav.element = 'newrequests';
    if (localStorage.getItem('loggedin') === 'yes') {
      this.meService.getMe().subscribe(data => {
          this.me = data;
        },
        error => {
          console.log(error);
        },
        () => this.assignmentService.getAssignments().subscribe(data => {
            this.assignments = data;
          },
          error => {
            console.log(error);
          },
          () => {
            this.setRequests();
          }));
    } else {
      this.router.navigate(['']);
    }
  }

  onLogout() {
    this.authService.logout();
  }

  onLogin() {
    this.authService.login();
  }

  private setRequests() {
    this.assignments.forEach(item => {
      if (this.me.mail.toLowerCase() === item.lecturer.toLowerCase()) {
        this.parseRequests(item.request, item.name);
      }
    });

    this.ready = true;
  }

  private parseRequests(toSplit, name) {
    const split = toSplit.split(',');

    split.forEach(item => {
      this.requests.push(new Request(item, name));
    });
  }
}

Это код со страницы:

<app-navbar-component></app-navbar-component>
<div *ngIf="ready">
  <div *ngFor="let request of requests">
    <p class="lead">{{request.user}}</p>
  </div>
</div>

Это функция в моем сервисе:

getAssignments() {
    return this.http.get(this.BASE_API_URL + '/assignments').catch(this.onError);
  }

Я не получаю ошибок. Запросы загружаются (проверено через console.log). Единственная проблема заключается в том, что страница отображается до завершения загрузки данных.

Любые идеи?

Заранее спасибо!


person abstract christmas tree    schedule 10.04.2018    source источник
comment
Да, это правильно. HTTP-запрос является асинхронным, поэтому он не ожидает завершения.   -  person martin    schedule 10.04.2018
comment
Как мне обойти это? Я думал, что *ngIf сработает...   -  person abstract christmas tree    schedule 10.04.2018
comment
Что обойти? Отрисовываются ли данные, когда запросы наконец завершаются?   -  person Roberto Zvjerković    schedule 10.04.2018
comment
Если вы не хотите, чтобы страница отображалась до получения данных, вы можете использовать защиту разрешения маршрутизатора.   -  person siva636    schedule 10.04.2018
comment
Компонент не отображается после завершения запросов.   -  person abstract christmas tree    schedule 10.04.2018


Ответы (2)


Вы пробовали использовать разрешение?

создайте имя распознавателя, которое оно присваивает-details.resolver.ts

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {MeService} from '../services/me.service';

@Injectable()
export class AssignmentsDetailsResolver implements Resolve<any> {

  constructor(api: MeService){}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
   return this.api.getAssignments();
  }

}

Затем в конфигурации вашего маршрута сделайте это так

{
  path: 'your_path',
  component: NewrequestComponent,
  resolve: { AssignmentsDetails: AssignmentsDetailsResolver }
}

Затем в вашем NewrequestComponent убедитесь, что вы импортируете ActivatedRoute

import { ActivatedRoute } from '@angular/router'

и в вашем конструкторе назовите это так

 constructor(private meService: MeService,
              private authService: AuthService,
              private assignmentService: AssignmentService,
              private router: Router,
              public nav: NavbarService,
              private activateRoute: ActivatedRoute) {

   this.activateRoute.data.subscribe((response) => {
       //to get the response
       console.log(response.AssignmentsDetails);
     });
  }

А также убедитесь, что вы зарегистрировали «AssignmentsDetailsResolver» в свойстве провайдера вашего модуля.

Надеюсь, это поможет вам.

person John Velasquez    schedule 10.04.2018
comment
Метод разрешения здесь является точным ответом на этот вопрос. - person th3n3wguy; 10.04.2018

Да Поскольку вызов службы является асинхронным, данные не поступают сразу после вызова подписки.

Но в вашем коде вы не устанавливаете готовую переменную в значение true после получения данных. Таким образом, вы не видите никаких данных на странице. Установите его в true, как только вы получите данные

this.me = data;
this.ready =true;

или управлять через оператора безопасной навигации.

person Sajeetharan    schedule 10.04.2018
comment
Спасибо за помощь. Я думаю, вы следили за готовой частью. Я устанавливаю ready на true в функции setRequests(). - person abstract christmas tree; 10.04.2018
comment
Да. Я заметил, что когда я устанавливаю значение true в указанном вами месте, оно становится истинным в компоненте. Однако это слишком рано. Данные, которые он использует, к тому времени еще не были загружены. Мне нужны данные о заданиях. - person abstract christmas tree; 10.04.2018
comment
вызвать setrequests внутри подписки - person Sajeetharan; 10.04.2018
comment
ничего не меняет к сожалению - person abstract christmas tree; 10.04.2018
comment
я уверен, что у вашего метода parseRequest есть проблема. просто проверьте, есть ли в вашем массиве данные - person Sajeetharan; 10.04.2018
comment
Я тщательно проверил этот метод. В массиве есть данные... Ready просто не становится истинным в компоненте. - person abstract christmas tree; 10.04.2018