如何让 async/await 等待 Observable 返回

vai*_*akh 3 javascript asynchronous promise observable rxjs

对 Angular 相当陌生,并且在 Promises、Observables 和 async/await 方面遇到困难。

  • 我有一个功能需要当前用户详细信息来执行某些任务。
  • 为此,我编写了一个获取用户详细信息方法,该方法返回一个承诺,并且任务在“then”部分内处理。
  • fetch 方法本身调用另一个方法,该方法调用 http.get 从数据库获取用户详细信息,并返回一个 Observable。
  • 我在这里使用 async/await 函数来等待 http.get 返回。

然而,这似乎不起作用。我感觉这与 Observables/subscribe 的工作方式有关,但我无法解决它。

代码片段:

    initPage() {
      fetchCurrentUserDetails().then((user) => { //tasks dependent on current user
        //task 1
        //task 2
      });
    }

    fetchCurrentUserDetails(): Promise<any> {
      return Promise.resolve((async () => {
        let currentUser = this.global.getUser();// check if user is defined already
        let userId: string = sessionStorage.getItem('userid');

        if (currentUser == undefined) {
          let initProfile = new Promise(resolve => resolve(this.fetchDetailsFromDB(userId)));
          const profile: any = await initProfile; //Waits, but returns before the Observable comes back

          let user = new User();
          // initialize user with the fetched values
          user.id = profile.id; // Undefined, since value not returned yet
          user.name = profile.user_name; // Undefined, since value not returned yet
          // Set this user in a global variable
          this.global.setUser(user);
       }

       return this.global.getUser();
      })());
    }

    fetchDetailsFromDB(userId: string) {
      //callProfileService has nothing but the http.get statement
      this.callProfileService(userId).subscribe((response) => {
        let profile = response.body.response.data.user;
         return profile;
      });
    }


Run Code Online (Sandbox Code Playgroud)

编辑:添加我如何尝试使用 toPromise:

    fetchDetailsFromDB(userId: string) {
      this.callUserProfileService(userId).toPromise().then((response) => {
       let profile = response.body.response.data.user;
       return profile;
    });
Run Code Online (Sandbox Code Playgroud)

这是正确的方法吗?如果是这样,如何让await等待Observable返回?

tri*_*cot 6

事实上,您需要该toPromise()方法,但不要忘记返回该承诺(return回调中的 还不够——该函数fetchDetailsFromDB需要返回一个承诺)。

在代码的其余部分:这是一种反模式,可以使用Promise.resolvenew Promise就像这样:根据经验,当您已经有一个可以使用的承诺(例如,来自 API 函数调用)时,不要使用其中任何一个创建新的承诺)。

因此,您可以使用方法来做到这一点async

async fetchCurrentUserDetails(): Promise<any> {
//^^^^
    let currentUser = this.global.getUser();
    if (currentUser == undefined) {
      const userId: string = sessionStorage.getItem('userid');
      const profile: any = await this.fetchDetailsFromDB(userId);
      currentUser = new User();
      currentUser.id = profile.id;
      currentUser.name = profile.user_name;
      this.global.setUser(currentUser);
   }
   return currentUser;
}

async fetchDetailsFromDB(userId: string): Promise<any> {
   const response = await this.callUserProfileService(userId).toPromise();
   return response.body.response.data.user;
};
Run Code Online (Sandbox Code Playgroud)

  • 这真的很有帮助,谢谢!指出如何返回承诺以及有关反模式的教育。 (2认同)