Вызовы API и методы жизненного цикла в Angular

Я пытаюсь осмыслить angular и его методы жизненного цикла. Ниже приведен отрывок из моей проблемы. Я пытаюсь захватить пользователя, вошедшего в систему, а затем выполнить вызов API на свой сервер, используя user.id. Я попытался переместить второй вызов API в ловушку жизненного цикла, которая находится дальше по цепочке, но я постоянно получаю ошибки, указывающие, что this.user.id не определен. Когда я консоль регистрирую объект пользователя в ngafterviewchecked, он проходит. Любая помощь или общие советы по хукам жизненного цикла будут оценены. Это выполняется в файле app.component.ts. Мне очень повезло с методами жизненного цикла в React, но angular вызывает у меня зацикливание.

users:any;
userNouns:any;

ngOnInit(){
  this.http.get('http://localhost:8000/users/1')
    .subscribe((result)=>{this.user=result})
}

ngAfterViewChecked(){
  console.log(this.user);
  this.http.get(`http://localhost:8000/nouns/${this.user.id}`)
    .subscribe((result)=>{this.userNouns=result})
}

person UnhandledPromiseRejectionError    schedule 08.03.2020    source источник
comment
Вы можете переместить оба вызова в ngAfterViewChecked(), и первый вызов должен быть преобразован в обещание, поэтому после его выполнения вы должны выполнить второй вызов. Или вы можете выполнить вызов в событии oncompleted первого вызова, который гарантирует, что он завершен и пользователь назначен   -  person Eldho    schedule 08.03.2020


Ответы (1)


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

Вместо этого используйте оператор RxJS, чтобы связать второй запрос с первым запросом. Вы можете использовать switchMap или concatMap, чтобы связать одну наблюдаемую с другой. Вы можете использовать tap для любых побочных эффектов (чтобы делать что-нибудь).

users:any;
userNouns:any;

ngOnInit(){
  this.http.get('http://localhost:8000/users/1').pipe(
    tap(result => this.user = result),
    concatMap(user => this.http.get(`http://localhost:8000/nouns/${this.user.id}`)),
    tap(result => this.userNouns = result)
  ).subscribe(() => {
    const contents = this.userNouns.map(noun => noun.content);
    console.log(contents);
  });
}
person Kurt Hamilton    schedule 08.03.2020
comment
Потрясающие. Большое спасибо. Это сработало. Я попытался прикрепить к результату .map (функцию более высокого порядка), потому что я предполагаю, что это был массив объектов, но была выдана ошибка, указывающая, что это объект. Я попытался ввести: this.userNouns = this.userNouns.map ((ele) = ›ele.content) после наблюдаемой цепочки, но все еще внутри oninit ... но похоже, что он даже не оценил. Я пытаюсь проанализировать информацию, прежде чем манипулировать ею другими методами. Есть предложения, как это лучше сделать? - person UnhandledPromiseRejectionError; 10.03.2020
comment
Вы имеете в виду то же самое, что и я в своем измененном посте? Я изменил вашу версию, чтобы избежать перезаписи this.userNouns - это кажется неправильным. - person Kurt Hamilton; 10.03.2020