如何仅在第一个 Promise 出错时 return 一个不同的 Promise?

How do I return a different Promise only if first Promise errors out?

具体情况是:

也许我对 Promises 的理解还不够好。

这是我想做的事情的非工作代码,但我不知道语法是如何工作的。

getUserProfile() {
  return this.storage.get("userProfile")
    .then(user => {
      if (user == null) {
        throw new Error("no user profile");
      }
    }
    )
    .catch(error => {
      //I don't know how to return a different promise
      return this.getUserProfileWithHttpCall();
    }
  );
}

//I want to return this in getUserProfile() if "userProfile" doesn't exist in "storage"
getUserProfileWithHttpCall(): Promise < UserProfile > {
  return this.http.get(this.baseUrl + "/Account/GetUserInfo")
    .toPromise()
    .then(
    response => {
      this.storage.set("userProfile", response);
      return response;
    }
  );
}

this.storage 是来自“@ionic/storage”的存储空间

this.http 是 HttpClient '@angular/common/http'

对于你的想法,没有必要抛出任何错误。你可以这样做:

getUserProfile() {
  return this.storage.get("userProfile")
    .then(user => user || this.getUserProfileWithHttpCall()
  );
}

awaitasync方式:

async getUserProfile() {
  return (await this.storage.get("userProfile")) || this.getUserProfileWithHttpCall();
}

也许您想使用 Observables,因为它们现在很流行。您可以将其更改为:

getUserProfile() {
  return from(this.storage.get("userProfile")).pipe(
    concatMap((user) => user ? of(user) : this.getUserProfileWithHttpCall())
  );
}

您必须更改您的 getUserProfileWithHttpCall 然后:

getUserProfileWithHttpCall(): Observable<UserProfile> {
  return this.http.get(`${this.baseUrl}/Account/GetUserInfo`).pipe(
    tap((user:UserProfile) => this.storage.set("userProfile", user))
  )
}

整洁多了:)

最后,解释为什么你的方法不起作用,是因为你没有在 then 中返回用户,当它不为空时,如果你不想更改你的代码所以 'drastically',你也可以这样做:

getUserProfile() {
  return this.storage.get("userProfile")
    .then(user => {
      if (user == null) {
        throw new Error("no user profile");
      }

      return user; // you missed this one
    }
    )
    .catch(error => {
      //I don't know how to return a different promise
      // Like you already did
      return this.getUserProfileWithHttpCall();
    }
  );
}