Как заставить async / await ждать, пока Observable вернется - PullRequest
0 голосов
/ 06 ноября 2019

Довольно плохо знаком с Angular и борется с Promises, Observables и async / await.

  • У меня есть функция, которой требуются данные текущего пользователя для выполнения некоторых задач.
  • Для этого я написал метод извлечения сведений о пользователе, который возвращает обещание, и задачи обрабатываются внутричасть then.
  • Сам метод fetch вызывает другой метод, который вызывает http.get для получения сведений о пользователе из базы данных и возвращает Observable.
  • Я использовал здесь async / awaitчтобы функция ожидала возврата http.get.

Однако, похоже, это не работает. У меня такое ощущение, что это как-то связано с тем, как работают Observables / подписка, но я не могу решить это.

Фрагмент кода:

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


Редактировать: добавление того, как я пытался с toPromise:

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

Это правильный способ сделать это? Если да, то как заставить ждать, пока «Наблюдатель» не вернется?

Ответы [ 2 ]

2 голосов
/ 06 ноября 2019

Действительно, вам нужен метод toPromise(), но не забудьте вернуть это обещание (return в обратном вызове недостаточно - функция fetchDetailsFromDB должна * 1006)* возврат обещание).

В остальном коде: это антипаттерн, использующий Promise.resolve и new 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;
};
1 голос
/ 06 ноября 2019

Вы можете использовать обратный вызов

initPage() {
    fetchCurrentUserDetails((user) => {
        //task 1
        //task 2
    });
}

fetchCurrentUserDetails(callback) {
    const currentUser = this.global.getUser();

    if (!currentUser) {
        const userId: string = sessionStorage.getItem('userid');
        return this.callProfileService(userId).subscribe((response) => {
            const profile = response.body.response.data.user;
            let user = new User();
            user.id = profile.id;
            user.name = profile.user_name;
            this.global.setUser(user);
            return callback(user);
        });
    } else {
        return callback(currentUser);
    }
}

...