0

I am failing in retrieving data from Observable.

I can't find where the problem is. As far as I understand my code is correct.

private IsPrivateLocation(id: string):boolean
{
    this.service.isLocationPrivate(id).subscribe(res => {
        this.location = res;
     });
     return this.location.isPrivate;
}

this.location is still UNDEFINED after method call. This is service method:

public isLocationPrivate(id:string):Observable<Location>
{
    return this.http.post(AppConfig.azurefunc.locationUri, {
        id: id,
        operatorId: AppConfig.user.operatorId
    }).pipe(map(res =>res.json()));
}

Why does it still undefined? What am I doing wrong?

Update: I managed to find a workaround without waiting for observable. However, I tried all the things that were offered below and none of them worked. Maybe that has something to do with the fact that I'm using Angular2 beta.

Sofia Bo
  • 679
  • 1
  • 10
  • 20
  • Can you post code showing how you use the method? – joshua miller Sep 18 '19 at 11:27
  • Do you mean how I call IsPrivateLocation() method? Something like var isPrivate=IsPrivateLocation(id); – Sofia Bo Sep 18 '19 at 11:28
  • Basically, the line `return this.location.isPrivate;` is executed _before_ `this.location = res;` - the former runs in the same event clock tick, and the latter after the HTTP call goes out and response is received. – mbojko Sep 18 '19 at 11:31
  • I see that Observable doesn't fit me in my situation. I need to get the isPrivate value NOT asynchronously. I need to wait for it and only then go further. Is there way to return a Location, not an Observable from service's method? – Sofia Bo Sep 18 '19 at 11:48
  • Can you show us your workaround (you can just post it as an answer)? – mrak Sep 20 '19 at 10:34

3 Answers3

1

It's expected that it's undefined. As Observables are asynchronous. You should return an Observable from your IsPrivateLocation() method and then subscribe to it at the end of your chain.

igor_c
  • 1,200
  • 1
  • 8
  • 20
  • I tried to do so and I got the same result. is there any way that I can return boolean from service's method? Something like .toPromise()? – Sofia Bo Sep 18 '19 at 11:30
  • `toPromise()` is also async, it won't make any difference. Show please what you tried that didn't work – igor_c Sep 18 '19 at 11:33
  • I'll edit the question right now. Is there any way of returning `Location` from service's method `isLocationPrivate`, not an `Observable`? – Sofia Bo Sep 18 '19 at 11:39
  • I see that Observable doesn't fit me in my situation. I need to get the isPrivate value NOT asynchronously. I need to wait for it and only then go further. Is there way to return a Location, not an Observable from service's method? – Sofia Bo Sep 18 '19 at 11:45
0

The Observable does not work like that,

private LoadLocationPrivate(id:string){
 this.service.isLocationPrivate(id).subscribe(res => {
        this.location = res; 
        if(this.location.isPrivate){
           // Do something
        }else{
            // Do other thing
        }
     });
}

Call LoadLocationPrivate when you need to navigate.

Hope this helps

Phat Huynh
  • 772
  • 5
  • 16
  • The problem is that I don't need to bind it to a view. I need the value because if it's true, then I'll redirect to another component. – Sofia Bo Sep 18 '19 at 11:32
  • So you can move the code use to navigate into subscribe callback – Phat Huynh Sep 18 '19 at 12:26
  • Could you please show how to do it? I'm completely unfamiliar to typescript but I need to make some changes on front-end of our system. That's why I'm struggling with it. – Sofia Bo Sep 18 '19 at 12:40
0

As already mentioned, an Observable can be either synchronous or asynchronous. In your case the its asynchronous since you are using a http rest service.

Your option here ist to use async/await:

private async isPrivateLocation(id: string)
{
    const location = await this.service.isLocationPrivate(id);
    return this.location.isPrivate;
}

and to call the function:

const isPrivate = await this.isPrivateLocation(123);

(Of course this code may have some errors). Please see the docs for reference. https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/await

The other option would be to subscribe to the Observable and redirect in the callback, but from what I understand, it is not what you want to achieve.

mrak
  • 2,826
  • 21
  • 21
  • Sorry, what is `cost`? And regarding `isPrivateLocation` in your case: location is observable in this case and it doesn't have `isPrivate` property. – Sofia Bo Sep 18 '19 at 11:56
  • My mistake, "const" and not "cost". Have a look in the documentation: await is used to resolve the Promise / Observable – mrak Sep 18 '19 at 11:58
  • I've read it and tried it. Even if I use `await` location still has the type Observable, not just a Location. Thus, it doesn't have a property isPrivate. – Sofia Bo Sep 18 '19 at 12:16
  • Could you try: const isPrivate = await this.isPrivateLocation(123).toPromise(); – mrak Sep 18 '19 at 12:31
  • Then my function needs to return Promise, and then I don't know what to do with Promise<...> object. – Sofia Bo Sep 18 '19 at 12:42
  • Nope, your function still returns Observable, with "toPromise" you can convert it to Promise (https://www.learnrxjs.io/operators/utility/topromise.html) – mrak Sep 18 '19 at 12:50