javascript - observables - subscribe angular 2
¿Cómo devuelvo la respuesta de una llamada Observable/http/async en angular? (8)
Aquí el problema es que está inicializando
this.myEvents
en
subscribe()
que es un bloque asincrónico mientras está haciendo
console.log()
justo fuera del bloque
subscribe()
.
Entonces, se llama a
this.myEvents
console.log()
antes de que
this.myEvents
se inicialice.
Mueva su código console.log () también dentro de subscribe () y ya está.
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents);
});
}
Tengo un servicio que devuelve un observable que hace una solicitud http a mi servidor y obtiene los datos.
Quiero usar estos datos, pero siempre termino
undefined
.
¿Cuál es el problema?
Servicio :
@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)
}
}
Componente:
@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!
}
}
El resultado no está definido porque el proceso angular es asíncrono. puedes intentar lo siguiente:
async ngOnInit(){
const res = await this.es.getEventList();
console.log(JSON.stringify(res));
}
Hacer una llamada http en angular / javascript es una operación asincrónica. Entonces, cuando realice una llamada http, asignará un nuevo hilo para finalizar esta llamada y comenzará la ejecución de la siguiente línea con otro hilo. Es por eso que está obteniendo un valor indefinido. así que haga el cambio a continuación para resolver esto
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //<-this become synchronous now
});
Los observables son vagos, por lo que debe suscribirse para obtener el valor. Lo suscribió correctamente en su código pero simultáneamente registró la salida fuera del bloque ''suscribir''. Por eso es ''indefinido''.
ngOnInit() {
this.es.getEventList()
.subscribe((response) => {
this.myEvents = response;
});
console.log(this.myEvents); //Outside the subscribe block ''Undefined''
}
Entonces, si lo registra dentro del bloque de suscripción, registrará la respuesta correctamente.
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //Inside the subscribe block ''http response''
});
}
Puede usar asyncPype si usa myEvents solo en la plantilla.
Aquí ejemplo con asyncPype y Angular4 HttpClient https://stackblitz.com/edit/angular-rhioqt?file=app%2Fevent.service.ts
Simplemente puedes probar este método
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'');
}
También asegúrese de asignar su respuesta a una salida json. De lo contrario, devolverá texto sin formato. Lo haces así:
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;})
}
Razón:
La razón por la que no está
undefined
es que está realizando una operación asincrónica.
Lo que significa que llevará algún tiempo completar el método
getEventList
(dependiendo principalmente de la velocidad de su red).
Así que echemos un vistazo a la llamada http.
this.es.getEventList()
Después de que realmente haga ("dispare") su solicitud http con
subscribe
, estará
esperando
la respuesta.
Mientras espera, JavaScript ejecutará las líneas debajo de este código y si encuentra asignaciones / operaciones sincrónicas, las ejecutará de inmediato.
Entonces, después de suscribirse a
getEventList()
y esperar la respuesta,
console.log(this.myEvents);
la línea se ejecutará de inmediato.
Y su valor no está
undefined
antes de que llegue la respuesta del servidor (o lo que sea que haya inicializado en primer lugar).
Es similar a hacer:
ngOnInit(){
setTimeout(()=>{
this.myEvents = response;
}, 5000);
console.log(this.myEvents); //This prints undefined!
}
Solución:
Entonces, ¿cómo superamos este problema? Utilizaremos la función de devolución de llamada, que es el método de
subscribe
. Porque cuando los datos lleguen del servidor estarán dentro de lasubscribe
con la respuesta.
Entonces cambiando el código a:
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //<-- not undefined anymore
});
imprimirá la respuesta ... después de un tiempo.
Lo que debes hacer:
Puede haber muchas cosas que hacer con su respuesta además de simplemente registrarla;
debe realizar todas estas operaciones dentro de la devolución de llamada (dentro de la función de
subscribe
), cuando lleguen los datos.
Otra cosa a mencionar es que si vienes de un fondo de
Promise
, la devolución de llamada corresponde a
subscribe
con observables.
No debe intentar cambiar una operación asíncrona a una operación de sincronización (no es que pueda). Una de las razones por las que tenemos operaciones asíncronas es para no hacer que el usuario espere a que se complete una operación mientras puede hacer otras cosas en ese período de tiempo. Suponga que una de sus operaciones asíncronas tarda 3 minutos en completarse; si no tuviéramos las operaciones asíncronas, la interfaz se congelaría durante 3 minutos.
Lectura sugerida:
El crédito original a esta respuesta es: ¿Cómo devuelvo la respuesta de una llamada asincrónica?
Pero con la versión angular2 se nos presentó el mecanografiado y los observables, por lo que, con suerte, esta respuesta cubre los conceptos básicos del manejo de una solicitud asincrónica con observables.