Неопределенная переменная уже объявила, когда получает данные из API в ngOnInit - PullRequest
0 голосов
/ 04 марта 2020

Я пытаюсь получить данные из nodeJS API с angular, у меня объявлена ​​переменная, и я хочу повлиять на ответ сервера на нее, вот мой код:

export class SondageSingleComponent implements OnInit, AfterViewInit {
  @ViewChild('containerPieChart') element: ElementRef;
  survey: any = {};
  currentUser: any;
  statistics: any;

  colorCounter: any = 0;
  d3Colors: any[] = ["#3182bd", "#6baed6", "#9ecae1", "#c6dbef", "#e6550d"];

  private host: D3.Selection;
  private svg: D3.Selection;
  private width: number;
  private height: number;
  private radius: number;
  private htmlElement: HTMLElement;
  private pieData = [];

  constructor(
    private http: HttpClient,
    private route: ActivatedRoute,
    private router: Router,
    private toastr: ToastrService
  ) { }

  ngOnInit() {
    this.route.params.subscribe(params => {
      this.http.get('/api/surveys/' + params.id).subscribe(survey => {
        this.survey = survey;
       // console.log(this.survey)
       debugger
        this.http.get('/api/surveys/getStatistics/' + params.id).subscribe(statistics => {
          this.statistics = statistics;
          this.statistics.options.forEach(option => {
            this.pieData.push(option.number);
            option.color = this.d3Colors[this.colorCounter];
            this.colorCounter = this.colorCounter + 1;
          });
        });
      }, error => {
        if (error.status === 400) {
          this.showError(error.error.error, 'Erreur!');
          if (error.error.error === 'Le sondage demandé n\'existe plus!') {
            this.router.navigateByUrl('/sondage');
          }
        }
      });
    });

  }

данные успешно поступают со стороны узла, и когда я пытаюсь повлиять на данные, чтобы проверить переменную и попробовать, любой может сказать, почему не может прочитать this.survey?

Ответы [ 2 ]

0 голосов
/ 04 марта 2020

Золотое правило с наблюдаемыми : не вкладывать подписки!

Похоже, что вы хотите:

  1. Прослушать изменения параметров маршрута
  2. Сделайте 2 http-запроса на основе параметра маршрута
  3. Обновите диаграмму на основе ответов http

Прослушивание this.route.params - хорошее начало для # 1.

Во-вторых, используйте switchMap для запуска новой наблюдаемой. И используйте forkJoin для одновременного вызова нескольких наблюдаемых.

ngOnInit() {
  this.route.params.pipe(
    switchMap(params => forkJoin({
      survey: this.http.get('/api/surveys/' + params.id),
      statistics: this.http.get('/api/surveys/getStatistics/' + params.id)
    }))
  ).subscribe(result => {
    this.survey = result.survey;
    this.statistics = result.statistics;
    this.updateChart(result.statistics);
  }, 
    error => this.handleError(error)
  );
}

private handleError(error) {
  if (error.status === 400) {
    this.showError(error.error.error, 'Erreur!');
    if (error.error.error === 'Le sondage demandé n\'existe plus!') {
      this.router.navigateByUrl('/sondage');
    }
  }
}

private updateChart(statistics) {
  statistics.options.forEach(option => {
    this.pieData.push(option.number);
    option.color = this.d3Colors[this.colorCounter];
    this.colorCounter = this.colorCounter + 1;
  });  
}

DEMO: https://stackblitz.com/edit/angular-m4agxv

Angular <8 </strong>

forkJoin({}) можно использовать только с Rx JS 6,5 (Angular> = 8). Для более ранних версий вам придется передать массив наблюдаемых.

ngOnInit() {
  this.route.params.pipe(
    switchMap(params => forkJoin([
      this.http.get('/api/surveys/' + params.id),
      this.http.get('/api/surveys/getStatistics/' + params.id)
    ]))
  ).subscribe(result => {
    this.survey = result[0];
    this.statistics = result[1];
    this.updateChart(result[1]);
  }, 
    error => this.handleError(error)
  );
}
0 голосов
/ 04 марта 2020

Вот как я бы это реализовал (взгляните на комментарии к коду)

ngOnInit() {
    this.route.params
        .subscribe(params => {
            this.http.get('/api/surveys/' + params.id)
                .pipe(
                    take(1),
                    // using switchMap is a lot better than subscribing
                    switchMap(survey => {
                        this.survey = survey;
                        return this.http.get('/api/surveys/getStatistics/' + params.id)
                    })
                )
                .subscribe(statistics => {
                    const newPieData = []
                    // using .map is a better use of javascript
                    statistics.options = statistics.options
                        .map(option => {
                            newPieData.push(option.number);
                            this.colorCounter = this.colorCounter + 1;
                            option.color = this.d3Colors[this.colorCounter];
                            return option;
                        });
                    this.pieData = [...this.pieData, ...newPieData];
                    // change this.statistics reference only at the end
                    // a change triggers the angular cycle
                    this.statistics = statistics;
                }, error => {
                    if (error.status === 400) {
                        this.showError(error.error.error, 'Erreur!');
                        if (error.error.error === 'Le sondage demandé n\'existe plus!') {
                            this.router.navigateByUrl('/sondage');
                        }
                    }
                });
        });
}

Я бы действительно рекомендовал использовать типы.

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

...