【问题标题】:Promise is resolved successfully before the funcion has finished using Angular and Ionic在函数完成使用 Angular 和 Ionic 之前,Promise 已成功解决
【发布时间】:2020-04-24 02:34:05
【问题描述】:

我创建了一个服务,该服务具有从 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();
  });  
}

【问题讨论】:

    标签: angular typescript ionic4 es6-promise angular-promise


    【解决方案1】:

    问题是您的函数logIn 在异步调用this.http.post 中设置了this.token 的值,因此当您return this.token; 时尚未分配它。你要早点回来。如果你想使用 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

    希望对你有帮助。

    【讨论】:

    • 谢谢!那行得通!也许使用 Observable 会更好?
    • 是的,使用 observable 就可以解决问题,而且它比 Promise 有一些优势。看看@Tomasz Flis 的回答。如果答案有帮助,别忘了点赞。
    【解决方案2】:

    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();
        });  
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-05
      • 2018-04-28
      • 2020-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-07
      • 2019-03-31
      • 2019-03-07
      相关资源
      最近更新 更多