0

I have problem of returning a value from a method, the value is always undefined and the promise will only yield the value after the method has returned.

I have tried observable but not getting the desired results.

import { Router } from "@angular/router";
import { JwtHelperService } from "@auth0/angular-jwt";
import { HttpClient } from "@angular/common/http";
import { map } from "rxjs/operators";
import { BehaviorSubject, Observable, of, Subject } from "rxjs";



interface ServerStatus {
  status: string;
}

interface BaseApi {
  baseURL: string;
  apiURL: string;
}

const helper = new JwtHelperService();

@Injectable({
  providedIn: "root"
})
export class AuthService {
  public token: string = "";

  public api: string;

  constructor(
    private httpService: HttpClient,
    private router: Router
  ) {

  }

  public decodedToken: JSON;
  public role: string;

  public timersubscribe: any;
  public myDate: Date;

  public stage: number;

  public tmp: any;



  getStage() {
    let url ;

    this.getApi().then(ret => url = ret))

    //this will appear only after the return is done
    console.log(url);

    //the url is always undefined
    return this.httpService.get<ServerStatus>(url);
  }



  getApi() {
    return this.httpService.get<BaseApi>("../../assets/api.json").toPromise().then(result => {
      return result.apiURL;
    })
  }

}

I want the promise to resolved to string before the method ( getStage() ) return.

AlbertK
  • 429
  • 2
  • 8
  • 21
  • Beside the question, but I suggest you embrace the observables instead of converting to promise. Observables are awesome with so many operators which are useful :) – AT82 Sep 10 '19 at 10:34
  • Why can't the promise or observable to returned synchronously. I need to return the URL (configuration) from a json file and use it every where and not call call an observable very time I need it. – AlbertK Sep 10 '19 at 10:38
  • welcome to the asynchronous world of JavaScript. You cannot make this synchronous, this is just how it works in JS :) – AT82 Sep 10 '19 at 10:41
  • You could consider using APP_INITIALIZER to fetch the url once when app is initialized, store it in a variable in a service and use it everywhere you need. – AT82 Sep 10 '19 at 10:43
  • Also, why store it as JSON if it's a local file? Why not as a variable? – AT82 Sep 10 '19 at 10:48

4 Answers4

0

You can use async await

async getStage() {
    let url = await this.getApi();

    //this will appear only after the return is done
    console.log(url);

    //the url is always undefined
    return this.httpService.get<ServerStatus>(url);
}
Lahiru Chandima
  • 22,324
  • 22
  • 103
  • 179
0

Hi your problem is how you resolve and return your promises .. try with this:

 getStage() {

return new Promise<string>((resolve,reject)=>{

 let url ;

        this.getApi().then(ret => {

        url = ret
        //this will appear only after the return is done
        console.log(url);

        //the url is always undefined
        this.httpService.get<ServerStatus>(url).then((res)=>{
resolve(res)

});


        })


      }



      getApi() {
        return new Promise<string>((resolve,reject)=>{
     this.httpService.get<BaseApi>("../../assets/api.json").toPromise().then(result => {
          resolve( result.apiURL);
        })
        })
}
federico scamuzzi
  • 3,708
  • 1
  • 17
  • 24
0

You can't receive a plain string from a promise - a promise is async so you have to handle it async. In js there isn't a method like "wait for promise"

I would say do something like that:

getStage(): Promise<any> {
    return this.getApi().then(url => {
        return this.httpService.get<ServerStatus >(url).toPromise();
    });
}

Here you return a Promise from getStage, here you can also return an observable (like that:).

getStage(): Observable<any> {
    return this.getApi().then(url => {
        return this.httpService.get<ServerStatus >(url);
    });
}

But then don't forget to subscribe ;)

getStage().subscribe(...);
Flo
  • 1,179
  • 3
  • 15
  • 43
0

use async await function like

async getStage() { let url = await this.getApi();

//url won't be undefined here
return this.httpService.get<ServerStatus>(url);

}

  • But with async it will return as a promise. I just want to be pure string not another promise form a promise. – AlbertK Sep 10 '19 at 09:51