Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - Return data directly from an Observable

I've been banging my head against this one trying to figure it out, and no amount of documentation I've been able to read has given me an answer to my question.

I have a service which is speaking directly to an API and returning an observable event which under normal circumstances I would subscribe to and do what I want with the data, however in a secondary service which utilizes the requests from the restful service, I need to be able to return values from the request.

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

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

In the quick example above, I want to know if there is any way I can return res from getSomething() within returnSomething(). If it's not achievable in this way, what is the alternative? I will add that the _restService is pretty heavily relied upon and I don't really want to start messing with that.

like image 314
Sidriel Avatar asked Jun 16 '16 18:06

Sidriel


People also ask

How do we get the value back from an observable in our component?

Observable values can be retrieved from any locations. The source sequence is first pushed onto a special observer that is able to emit elsewhere. This is achieved with the Subject class from the Reactive Extensions (RxJS). Store value onto the observer.

Can Angular pipe return observable?

Angular expects pipes to be synchronous. They should return a resolved value, not a Promise or an Observable . To use a pipe that returns an unresolved value, you can use Angular's async pipe.

How does Angular display observable data?

It is very easy to display observable in angular using the async pipe. import { Component, OnInit } from '@angular/core'; import { Observable, of } from 'rxjs'; @Component({ selector: 'app-demo', templateUrl: './demo.


2 Answers

Since http calls and the like are async, you get an Observable instead of a synchronous value returned. You have to subscribe to it, and in the callback in there you get the data. There is no way around that.

One option would be to place your logic in the subscribe call

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

But the way I like doing it is to add a callback, to inject the logic from outside (maybe a component, maybe another service):

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

And in your component or wherever:

this._yourService.getSomething((data) => {
    // do something here
    console.log(data);
});
like image 65
rinukkusu Avatar answered Oct 12 '22 11:10

rinukkusu


I had a similar issue. My solution was to convert the observable into a promise with .toPromise() (and use async - await to return it and catch errors). You can convert your code into something like:

 async getSomething() {
     try{
         return await this._restService.addRequest('object', 'method').run().toPromise()
      } catch (err){
       console.error(err);
	  }
  }
like image 30
hjbello Avatar answered Oct 12 '22 10:10

hjbello