Angular 2-Devuelve datos directamente desde un Observable


He estado golpeando mi cabeza contra este tratando de averiguarlo, y ninguna cantidad de documentación que he podido leer me ha dado una respuesta a mi pregunta.

Tengo un servicio que está hablando directamente a una API y devolviendo un evento observable al que, en circunstancias normales, me suscribiría y haría lo que quisiera con los datos, sin embargo, en un servicio secundario que utiliza las solicitudes del servicio restful, necesito poder devolver valores del servicio restful. solicitud.

getSomething() {
    return this._restService.addRequest('object', 'method').run()
        .subscribe(
            res => {
                res;
            },
            err => {
                console.error(err);
            }
        );
}

returnSomething() {
    return this.getSomething();
}

En el ejemplo rápido anterior, quiero saber si hay alguna forma en que pueda devolver res desde getSomething() dentro de returnSomething(). Si no es alcanzable de esta manera, ¿cuál es la alternativa? Agregaré que el _restService es bastante confiable y realmente no quiero comenzar a jugar con eso.

Author: Sidriel, 2016-06-16

3 answers

Dado que las llamadas http y similares son asincrónicas, se obtiene un Observable en lugar de un valor síncrono devuelto. Tienes que suscribirte a él, y en la devolución de llamada de allí obtienes los datos. No hay forma de evitarlo.

Una opción sería colocar su lógica en la llamada subscribe

getSomething() {
    return this._restService.addRequest('object', 'method').run()
        .subscribe(
            res => {
                // do something here
                res;
            },
            err => {
                console.error(err);
            }
        );
}

Pero la forma en que me gusta hacerlo es agregar una devolución de llamada, inyectar la lógica desde fuera (tal vez un componente, tal vez otro servicio):

getSomething(callback: (data) => void) {
    return this._restService.addRequest('object', 'method').run()
        .subscribe(
            res => {
                callback(res);
            },
            err => {
                console.error(err);
            }
        );
}

Y en su componente o donde sea:

this._yourService.getSomething((data) => {
    // do something here
    console.log(data);
});
 37
Author: rinukkusu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-16 19:05:22

Yo no usé esto, pero creo que debería funcionar en teoría (:

// service.ts
getSomething() {
  let subject: Subject = new Subject();
  this._restService.addRequest('object', 'method').run()
    .subscribe(subject);
  return subject;
}

// this can be removed (;
returnSomething() {
  return this.getSomething();
}

// component.ts
ngOnInit() {
  this.service.returnSomething()
    .subscribe(res => console.log(res), err => console.log(err));
}

Revisa subject docs para más información. Puede usar diferentes tipos de sujeto, por ejemplo BehaviorSubject tiene value propiedad a la que puede acceder...

ngOnInit() {
  // if you use BehaviorSubject
  this.service.returnSomething().value
}

Aquí está el émbolo de trabajo ...

 1
Author: Sasxa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-16 19:50:28

Tuve un problema similar. Mi solución fue convertir lo observable en una promesa con .toPromise() (y use async - await para devolverlo y detectar errores). Puedes convertir tu código en algo como:

 async getSomething() {
     try{
         return await this._restService.addRequest('object', 'method').run().toPromise()
      } catch (err){
       console.error(err);
	  }
  }
 0
Author: hjbello,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-05 08:06:59