25

I have a service that has a method foo. Inside the method I subscribe to an observable (http-client).

foo () : boolean
{
  let ret : false;

  this.http.get ("/blabla").subscribe (
  (resp) =>
  {
    ret = true;
  }

  return ret;
);

I like to return a boolean value from foo that depends on the get. That is not working because http.get is asynchrouns - return is called before http.get finished.

How can I make this synchronous?

EDIT

Returning the observable instead boolean is not an option here. That is because I handle the response of get in foo (not shown here) but I also need to act out of foo depending of its return.

EDIT2

I extended my sample with pipe and tap. Now I return the http.get-observable for outside the service and I process the http.get-result with tap.

foo () : Observable <any>
{
  return this.http.get ("/blabla").pipe (tap (x => handlehere ()));
}

As far I see there is only one uglyness with it. I have the complexity of parsing the get-result inside AND outside of foo. I would prefer a simple boolean outside of foo.

chris01
  • 10,921
  • 9
  • 54
  • 93
  • 1
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Igor Sep 24 '18 at 18:27
  • 2
    `How can I make this synchronous?` <= you don't, you return an observable or a promise. `Returning the observable instead boolean is not an option here` <= why? – Igor Sep 24 '18 at 18:28
  • 2
    Then you have no option because synchronous code could become asynchronous in one operation, but asynchronous code could never become synchronous again – smnbbrv Sep 24 '18 at 18:29
  • `but I also need to act out of foo depending of its return` <= then make the acting on the call also occur asynchronously. Once you understand the pattern used for asynchronous javascript (typescript) code/interaction it will be much easier for you to write your application. There is generally a fair amount of asynchronous interaction in applications because they interact with external resources (user input, databases, network streams, etc). You will be a better programmer for it. – Igor Sep 24 '18 at 18:35
  • Returning an Observable would be also possible but then it must be related to http.get. I do not know how to do that. – chris01 Sep 24 '18 at 18:35
  • Follow along with the [Tour of heroe's](https://angular.io/tutorial/toh-pt6) tutorial or read up on the [http client](https://angular.io/guide/http) documentation. Both are rich in examples of how to do just that. – Igor Sep 24 '18 at 18:37
  • your 2nd update looks good, stay on that direction – Jota.Toledo Sep 24 '18 at 19:28

1 Answers1

27

This method can only run asynchronously so you don't have a lot of option. Returning the obsersable and subscribe or return a promise. Perhaps returning a Promise will suite more your need in term of comprehention.

In your service : the foo method :

async foo() {
   const result = await this.http.get("/blabla").toPromise();

   // do what you want with result 

   return result;
}

How to call it :

this.myService.foo().then( (result) => {
   // Do what you want with the result
});
xrobert35
  • 2,488
  • 1
  • 16
  • 15
  • 2
    toPromise() is deprecated and will be removed in v8. Anyone found some simillar workaround? – Jake_3H May 10 '22 at 11:38
  • 4
    You can use ` firstValueFrom(observable)` instead of toPromise() – Santhosh Nagaraj Oct 28 '22 at 11:02
  • 1
    this answer is not synchronous in angular. firstValueFrom(observable) is also not synchronous, because you have to await both call's, which means other resources can do stuff while waiting on the result. – gangfish Mar 27 '23 at 15:03