Дождитесь завершения функций, а затем верните объект

#typescript #rxjs #nestjs

Вопрос:

Я хочу вернуть недавно обновленный объект. Но когда я пытаюсь присвоить значения с помощью методов с цепочкой каналов, это не работает и возвращает начальные значения.

Как лучше всего назначать с помощью цепных функций и возвращать объект ?

Вот код:

 currentUser: UserInterface = {
    accessToken: '',
    userID: '',
    name: '',
    email: '',
    picture: '',
    pageList: [],
    activePageID: 0,
    activePage: {
      name: '',
      pageID: '',
      instagramID: '',
      categoryID: '',
      tasks: [],
    },
  };

  login(user: FacebookLoginInterface) {
      this.generateLongUserToken(user.accessToken).pipe(
      map((response) => {
        this.currentUser.accessToken = response.access_token;
        this.getUserPages(this.currentUser.accessToken).pipe(
          map((response) => {
            this.currentUser.pageList = response;
            this.getInstagramBusinessAccount(
              this.currentUser.pageList[0].id,
              this.currentUser.accessToken,
            ).pipe(
              map((response) => {
                this.currentUser.activePage.instagramID =
                  response.instagram_business_account.id;
              }),
            );
          }),
        );
      }),
    ); 

    return {
      access_token: this.currentUser,
    };
  }
 

Комментарии:

1. Что именно такое «метод с цепочкой из труб». Насколько мне известно, это не собственная концепция javascript/машинописного текста.

2. «Труба» также не является концепцией NextJS. По крайней мере, я этого не знаю… Ты звонишь this.generateLongUserToken(user.accessToken) . Что возвращает этот метод?

3. @Elias Я развиваюсь в «nestjs». Он возвращает новый токен с длительным сроком действия, когда я даю токен с коротким сроком действия. Что я хочу, так это: есть 2-3 метода, которые возвращают значения из api facebook. И мне нужно назначить их своим коллегам в «CurrentUser». Но он не ждет, пока они закончат, и мгновенно возвращает «текущего пользователя», или назначение аналогов в методах не работает.

4. Mh, какой тип текста он возвращает?

5. Если this.generateLongUserToken(user.accessToken) возвращает UserInterface , не должно ли быть pipe функции в этом интерфейсе?

Ответ №1:

Используйте обещания

 login() {
  return new Promise((resolve, reject) => {
      this.generateLongUserToken(user.accessToken).pipe(
      map((response) => {
        this.currentUser.accessToken = response.access_token;
        this.getUserPages(this.currentUser.accessToken).pipe(
          map((response) => {
            this.currentUser.pageList = response;
            this.getInstagramBusinessAccount(
              this.currentUser.pageList[0].id,
              this.currentUser.accessToken,
            ).pipe(
              map((response) => {
                this.currentUser.activePage.instagramID =
                  response.instagram_business_account.id;
                // If I understand correctly, at this point `currentUser`
                // is ready to be returned, so resolve the promise here
                resolve() 
              }),
            );
          }),
        );
      }),
    ); 
  }).then(() => ({
    access_token: this.currentUser,
  }))
}

currentUser.login().then(user => {
  // Here user is updated
})
 

Кроме того, вы могли бы немного очистить его, чтобы иметь меньше уровней вложенности

 login() {
  return new Promise((resolve) => {
    this.generateLongUserToken(user.accessToken).pipe(
      map((response) => {
        this.currentUser.accessToken = response.access_token;
        resolve(response.access_token)
      })
    )
  }).then((accessToken) => new Promise((resolve) => {
    this.getUserPages(this.currentUser.accessToken).pipe(
      map((response) => {
        this.currentUser.pageList = response;
        resolve({pageList: response, accessToken})
      })
    )
  })).then(({pageList, accessToken}) => new Promise(resolve => {
      this.getInstagramBusinessAccount(
        this.currentUser.pageList[0].id,
        this.currentUser.accessToken,
      ).pipe(
        map((response) => {
          this.currentUser.activePage.instagramID =
              response.instagram_business_account.id;
          resolve()
        })
      )
  })).then(() => ({
    access_token: this.currentUser,
  }))
}
 

За исключением того, что это будет работать только в том случае, если функция in map будет вызвана один раз. Название map предполагает, что обратный вызов может быть вызван несколько раз, в этом случае это также не сработает. В любом случае, вы должны использовать обещания