1
votes

Consider the following function

Go(publicRoute: boolean, token: string) {
    let rtrn = {} as aaResult;

    if (publicRoute) {
        rtrn.Authenticated = true;
    }
    else {
        if (token != "" || this.userService.Get() != null) {
            if (this.userService.Get() != null) {
                rtrn.Authenticated = true;
            }
            else {
                this._authorize(token).subscribe(res => {
                    console.log("internal subscribe");
                    console.log(res);
                    this.userService.Set(new User(res));                      
                    if (this.userService.Get() != null) {
                        rtrn.Authenticated = true;
                        rtrn.User = this.userService.Get()
                    }
                    else
                        this._authenticate();
                }
                    ,
                    error => {
                        this._authenticate();
                    }
                )
            }
        }
        else {
            this._authenticate();
        }
    }

    return (Observable.of(rtrn));
}

If the first if is true the return data is correct. If the if is false the return data is {} because the function doesn't wait for the results of this._authorize. How can I make the function wait for the result of internal observable?

This is how the whole thing gets called, just in case:

this.AA.Go(this.publicRoute, this.internalToken).subscribe(res => { console.log(res) })

EDIT

Adding code for the authorize function turned into observable

private  _authorize(token: string, options?: any): Promise<User> {
    return this.http.get<User>(this.config.aa.autherizationUrl + "?token=" + token, {
        headers: this.Utils.SetRequestAppOptions(options === undefined ? {} : options),
    }).toPromise();
}
1
is UserService.Get() returning an Observable? - Chau Tran
No, it's just simple variable holder service. - americanslon
can you please add content of _authenticate()? - Chau Tran
I was planning to rewrite and add the code as an answer but anyway, my take would be place your return statement in the subscribe block. Then place couple more return statements in the function or use toPromise so you can async/await it without subscribing ;) - Chau Tran
I don't get it. If you want to return an observable then why do you subscribe? - a better oliver

1 Answers

1
votes

You should consider, since observables are asynchronous, changing the this._authorize return type to a promise. So then you can do await this._authorize.

The await specifically waits until the function is completely executed, before moving on. Await only works on promises, so you need to change the return type.

If the function is an observable. You can use .toPromise() to make it a promise in an easy way.

EDIT

Asuming that you have the method returning an observable, this should work. On promises, the result is stored on a variable, so you can't subscribe to it.

This shoud work:

import { from } from 'rxjs';

async function GoAsync(publicRoute: boolean, token: string) {
  let rtrn = {} as aaResult;

  if (publicRoute) {
      rtrn.Authenticated = true;
  }
  else {
      if (token != "" || this.userService.Get() != null) {
          if (this.userService.Get() != null) {
              rtrn.Authenticated = true;
          }
          else {
              try {
                 let res = await this._authorize(token); //wait for the response
                  console.log("internal subscribe");
                  console.log(res);
                  this.userService.Set(new User(res));
                  if (this.userService.Get() != null) {
                      rtrn.Authenticated = true
                      rtrn.User = this.userService.Get()
                  }
              }
              // avoid else's and catch, using finally.
              catch {
                  // error handle here
              }
          }
      }
      // allways perform this action, as stated in your code
      this._authenticate();
  }
  return (rtrn);
}

function Go(publicRoute: boolean, token: string) {
    return from(GoAsync(publicRoute,token))
}