Как вернуть ответ от наблюдаемого/http / async вызова в angular2?

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

сервис:

@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({...})
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!
  }
}

6 ответов


причина:

потому что это 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!
}


устранение:

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

таким образом, изменяя код:

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

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


что вы должны do:

может быть много вещей, чтобы сделать с вашим ответом, кроме как просто войти в него; вы должны сделать все эти операции внутри обратного вызова (внутри


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

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

также убедитесь, что вы сопоставляете свой ответ с выходом json. В противном случае он вернет обычный текст. Вы делаете это так:

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)=>{ return res.json();}) <!-- add call to json here
            .catch((err)=>{return err;})

}


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

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


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

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'
    });
}

вы можете просто попробовать этот метод-

let headers = new Headers({'Accept': 'application/json'});
let options = new RequestOptions({headers: headers});

return this.http
    .get(this.yourSearchUrlHere, options) // the URL which you have defined
    .map((res) => {
        res.json(); // using return res.json() will throw error
    }
    .catch(err) => {
        console.error('error');
    }