Обещание успешно решено до того, как функция закончила использовать Angular и Ionic - PullRequest
0 голосов
/ 23 апреля 2020

Я создал службу, у которой есть метод, который извлекает токен из API, который вызывает метод subscribe () для внутреннего использования. Этот метод вызывается из компонента и не возвращает Observable, только строку, содержащую токен.

Затем существует другой метод, который должен вызываться из компонента после получения токена, однако он всегда вызывается перед другим. Я даже пытался с async / await в компоненте, но он не работал.

// api.service.ts
logIn() {
  if(!this.token) {  
    this.http.post(this.apiURL + "/token/", {username: "test", password: "test"}, options).subscribe(response => {
    if(response.status == 200) {
        this.body = response.body;
        this.token = "Token " + this.body.token;
        window.sessionStorage.setItem("TOKEN_KEY", this.token);
        console.log(this.token);
    }
  }
  return this.token;
}

Как вы видите, метод просто возвращает токен, поэтому я создаю Promise в компоненте и как только он разрешается вызовом метода getProduct (), но он вызывается до того, как токен уже существует.

// product.component.ts

async getLogin() {
  const resp = await this.apiService.logIn();
  console.log(resp);
}

getMenu() {
  this.apiService.getMenu().subscribe(resp => {
    console.log(resp);
});

constructor(private apiService: APIService) {
  this.getLogin().then(resp => {
    console.log('Called');
    // Call before the token has already been created!
    this.getMenu();
  });  
}

Ответы [ 2 ]

0 голосов
/ 23 апреля 2020

В методе logIn() вы должны вернуть Observable.

logIn(): Observable<string> {
  return this.http
    .post(this.apiURL + "/token/", {username: "test", password: "test"}, options)
    .pipe(
        filter(response => response.status == 200),
        map(response => response.body.token),
        tap(token => {
           window.sessionStorage.setItem("TOKEN_KEY", `Token ${token}`);
        })
    );
}

И затем в конструкторе

constructor(private apiService: APIService) {
    this.getLogin().subscribe(token => {
        console.log('Called');
        // Call before the token has already been created!
        this.getMenu();
    });  
}
0 голосов
/ 23 апреля 2020

Проблема в том, что ваша функция logIn устанавливает значение this.token в асинхронном вызове this.http.post, поэтому, когда вы return this.token;, оно еще не назначено. Вы возвращаетесь рано. Если вы хотите go с подходом Promise , то logIn должен вернуть Promise

async logIn() {
  if(!this.token) {  
    return this.http.post(this.apiURL + "/token/", {username: "test", password: "test"}, options)
      .toPromise()
      .then(response => {
        if(response.status == 200) {
            this.body = response.body;
            this.token = "Token " + this.body.token;
            window.sessionStorage.setItem("TOKEN_KEY", this.token);
            console.log(this.token);

            return this.token; // important to return the token here
        }
      }
  }
  return this.token;
}

Обратите внимание, что я добавил async ключевое слово для функции logIn, изменив subscribe для toPromise, добавив .then и добавив в него return this.token.

Надеюсь, это поможет.

...