Как мне вернуть ответ от звонка "Observablehttpasync" под углом.

javascript angular asynchronous typescript observable


У меня есть служба, которая возвращает наблюдаемую информацию, которая отправляет http-запрос на мой сервер и получает данные. Я хочу использовать эти данные, но всегда получаю undefined . В чем проблема?

Service:

@Injectable()
export class EventService {

  constructor(private http: Http) { }

  getEventList(): Observable<any>{
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });

    return this.http.get("http://localhost:9999/events/get", options)
                .map((res)=> res.json())
                .catch((err)=> err)
  }
}

Component:

@Component({...})
export class EventComponent {

  myEvents: any;

  constructor( private es: EventService ) { }

  ngOnInit(){
    this.es.getEventList()
        .subscribe((response)=>{
            this.myEvents = response;
        });

    console.log(this.myEvents); //This prints undefined!
  }
}




Answer 1 eko


Reason:

Причина, по которой он не undefined заключается в том, что вы выполняете асинхронную операцию. Это означает, что для завершения метода getEventList потребуется некоторое время (в основном в зависимости от скорости вашей сети).

Итак,давайте посмотрим на http-звонок.

this.es.getEventList()

После того, как вы на самом деле сделаете («запустите») ваш http-запрос с subscribe вы будете ждать ответа. Во время ожидания javascript выполнит строки под этим кодом, и если он встретит синхронные назначения / операции, он выполнит их немедленно.

Поэтому после подписки на getEventList() и ожидания ответа,

console.log(this.myEvents);

Строка будет выполнена немедленно. И его значение не undefined до того, как ответ поступит с сервера (или к тому, что вы инициализировали в первую очередь).

Это похоже на то,что ты делаешь:

ngOnInit(){
    setTimeout(()=>{
        this.myEvents = response;
    }, 5000);

    console.log(this.myEvents); //This prints undefined!
}


Solution:

Итак, как мы можем преодолеть эту проблему? Мы будем использовать функцию обратного вызова, которая является методом subscribe . Потому что, когда данные поступают с сервера, они будут внутри subscribe с ответом.

Так что поменяйте код на:

this.es.getEventList()
    .subscribe((response)=>{
        this.myEvents = response;
        console.log(this.myEvents); //<-- not undefined anymore
    });

распечатает ответ...через некоторое время.


Что ты должен делать:

Может быть много вещей, связанных с вашим ответом, кроме регистрации его; Вы должны делать все эти операции внутри обратного вызова (внутри функции subscribe ), когда поступают данные.

Еще одна вещь, которую стоит упомянуть, это то, что если вы пришли из фона Promise , then callback соответствует subscribe с наблюдаемыми.


Что вы не должны делать:

Не следует пытаться изменить операцию асинхронизации на операцию синхронизации (не то,чтобы можно было).Одна из причин,по которой мы используем операции асинхронизации,заключается в том,что мы не заставляем пользователя ждать завершения операции,в то время как он может делать другие вещи за этот промежуток времени.Предположим,что одна из ваших операций асинхронизации занимает 3 минуты,если бы у нас не было операций асинхронизации,интерфейс был бы заморожен на 3 минуты.


Предлагаемое чтение:

Первоначальная благодарность этому ответу заключается в следующем: Как вернуть ответ от асинхронного вызова?

Но в релизе angleular2 нас познакомили с typecript и observables,поэтому этот ответ,надеюсь,охватывает основы обработки асинхронного запроса с наблюдаемыми.




Answer 2 RAVI PATEL


Вызов http в angularjavascript является асинхронной операцией.Поэтому при вызове http он назначит новый поток,чтобы закончить этот вызов и начать выполнение следующей строки с другим потоком.Вот почему вы получаете неопределенное значение.Поэтому внесите нижеуказанное изменение,чтобы разрешить следующее

this.es.getEventList()  
      .subscribe((response)=>{  
       this.myEvents = response;  
        console.log(this.myEvents); //<-this become synchronous now  
    });



Answer 3 Kliment Ru


Вы можете использовать asyncPype, если вы используете myEvents только в шаблоне.

Вот пример с asyncPype и Angular4 HttpClient https://stackblitz.com/edit/angular-rhioqt?file=app%2Fevent.service.ts




Answer 4 Kooldandy


Наблюдатели ленивы,так что вам нужно подписаться,чтобы получить стоимость.Вы подписывали его правильно в своем коде,но одновременно записывали вывод вне блока 'подписываться'.Вот почему он 'неопределенный'.

ngOnInit() {
  this.es.getEventList()
    .subscribe((response) => {
        this.myEvents = response;
    });

  console.log(this.myEvents); //Outside the subscribe block 'Undefined'
}

Таким образом,если вы зарегистрируете его внутри блока подписки,то он будет регистрировать ответ должным образом.

ngOnInit(){
  this.es.getEventList()
    .subscribe((response)=>{
        this.myEvents = response;
        console.log(this.myEvents); //Inside the subscribe block 'http response'
    });
}



Answer 5 Suneet Bansal


Проблема в том, что вы инициализируете this.myEvents в subscribe() который является асинхронным блоком, в то время как вы выполняете console.log() только из блока subscribe() . Поэтому console.log() this.myEvents до того, как this.myEvents будет инициализирован.

Пожалуйста,переместите ваш консольный.log()код,а также внутри функции subscribe(),и все готово.

ngOnInit(){
    this.es.getEventList()
        .subscribe((response)=>{
            this.myEvents = response;
            console.log(this.myEvents);
        });
  }