Как я могу изменить порядок подписки? - PullRequest
0 голосов
/ 28 мая 2019

Как я могу изменить порядок исполнения? У меня есть массив this.friend, мне нужно работать с этим массивом, но требуется, чтобы заполнить данными

this.listUserService.getUsers().subscribe(
    async (data: any) => {
           this.listUsers = data;
           await data.forEach((current: any) => {
                 if (current.name === userSession) {
                      this.user = current;
                      this.friendsService.getFriends(this.user.id).subscribe(response => {
                                console.log('last', response);//this runs second
                                this.friends = response;
                            });
                        }
                    });
                    console.log('friends', this.friends); //friend is clear, 
this runs first
                    this.listUsers = this.listUsers.filter(user => !this.friends.some(relationship => relationship[0].friend.id !== user.id));
                }
            );

Сообщения консоли отображаются в обратном порядке, как я могу изменить порядок, как только он заполнится, я хочу использовать функцию фильтра

Ответы [ 3 ]

2 голосов
/ 28 мая 2019

Нет необходимости смешивать обещания с наблюдаемыми.Кроме того, не стоит вставлять subscribe() методы друг в друга.Я бы порекомендовал вам обработать вышеуказанную операцию с операторами RxJS.

Сначала мы используем mergeMap , чтобы отобразить наблюдаемые значения из метода getUsers () из сервиса во внутреннюю наблюдаемую.

Затем мы используем forkJoin , чтобы дождаться завершения цикла Array.forEach(), прежде чем возвращать все наблюдаемые.Поскольку вы, похоже, знакомы с использованием Promises в JavaScript, на самом деле это похоже на Promise.all.

И последнее, но не менее важное: мы выполняем фильтрацию listUsers в блоке subscribe().Это обеспечит правильную обработку вашего асинхронного кода.

this.listUserService.getUsers().pipe(
  mergeMap(data => {
    this.listUsers = data;
    const observablesList = [];
    data.forEach((current: any) => {
      if (current.name === userSession) {
        observablesList.push(this.friendsService.getFriends(current.id));
      }
    });
    return forkJoin(observablesList);
  })
).subscribe(response => {
  // console.log(response) will give you the returned values from the looped getFriends()
  // handle the rest here

});
1 голос
/ 28 мая 2019

Это потому, что вы используете потоки RxJS неправильно. Сначала вы настраиваете свой поток, поэтому любой другой console.log будет запускаться первым. Поток Rx сам по себе асинхронный, поэтому вам не нужно async await. Другой console.log будет запущен, когда поток на самом деле вызывается и получает данные.

Путь RxJS был бы .pipe() вашим filter() внутри потока Rx.

Это не столько проблема Angular, это больше связано с RxJS. Вот пример того, как это может выглядеть:

   this.listUserService
  .getUsers()
  .pipe(
    tap(listUserData => {
      this.listUsers = listUserData;
    }),
    switchMap(data => {
      return this.friendsService.getFriends(data.id).pipe(
        tap(friends => {
          this.friends = friends;
        })
      );
    })
  )
  .subscribe();

switchMap переключается на другую наблюдаемую под водой, поэтому вам не нужны две подписки. Это считается хорошей практикой!

Я очень рекомендую потратить некоторое время на изучение RxJS, это сделает ваш опыт в Angular намного более приятным и продуктивным!

Я могу помочь вам с этим, если хотите!

1 голос
/ 28 мая 2019

Вместо этого вы можете попробовать использовать операторы RxJS, такие как switchMap , map и tap , чтобы управлять потоком наблюдаемого, включая выполнение побочных эффектов, таких как установка классаproperties.

В этом ответе предполагается, что в forEach () есть только один текущий пользователь, полученный из if (current.name === userSession) {, и, следовательно, this.friendsService.getFriends(user.id) выполняется только один раз.

import { map, switchMap, tap } from 'rxjs/operators'; // need to import operators

// ...

this.listUserService.getUsers().pipe(
  tap(users => this.listUsers = users), // side effect to set this.listUsers
  map(users => users.find(user => user.name === userSession)), // find current user
  switchMap(user => this.friendsService.getFriends(user.id)), // get friends of current user
  tap(friends => this.friends = friends), // side effect to set this.friends
  map(friends => this.listUsers.filter(user => this.friends.some(relationship => relationship[0].friend.id !== user.id)))
).subscribe(listUsers => {
  this.listUsers = listUsers;
});

Вам следуетОбязательно просмотрите документацию RxJS для получения дополнительной информации и примеров различных операторов.Также вам обязательно нужно улучшить обработку ошибок в случае, если текущий пользователь не найден или какой-либо из вызовов service / api завершится неудачей.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...