Как изменить порядок выполнения? У меня есть массив 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.info('last', response);//this runs second
this.friends = response;
});
}
});
console.info('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));
}
);
Сообщения консоли отображаются в обратном порядке, как я могу изменить порядок, когда он будет заполнен, я хочу использовать функцию фильтра
Нет необходимости смешивать обещания с наблюдаемыми. Кроме того, не рекомендуется вкладывать subscribe()
методы друг в друга. Я бы порекомендовал вам выполнить вышеуказанную операцию с операторами RxJS.
Во-первых, мы используем карта слияния для отображения наблюдаемых значений из метода getUsers() из службы во внутреннюю наблюдаемую.
Затем мы используем forkJoin, чтобы дождаться завершения цикла Array.forEach()
, прежде чем вернуть все наблюдаемые. Поскольку вы, кажется, знакомы с использованием промисов в 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.info(response) will give you the returned values from the looped getFriends()
// handle the rest here
});
Вместо этого вы можете попробовать использовать операторы RxJS, такие как переключательКарта, карта и кран, для управления потоком наблюдаемого, включая выполнение побочных эффектов, таких как установка свойств класса.
Этот ответ предполагает, что существует только один текущий пользователь, полученный в результате if (current.name === userSession) {
внутри forEach(), и, следовательно, 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 для получения дополнительной информации и примеров различных операторов. Также вам определенно потребуется улучшить обработку ошибок в случае таких ситуаций, как текущий пользователь не найден или какой-либо из вызовов службы/API не работает.
Надеюсь, это поможет!
Это потому, что вы неправильно используете потоки RxJS. Сначала вы настраиваете свой поток, чтобы любой другой console.info
запускался первым. Поток Rx сам по себе асинхронный, поэтому вам не нужно async await
. Другой console.info
будет работать, когда поток действительно вызывается и получает данные.
Способ 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 намного более приятным и продуктивным!
Я могу помочь тебе с этим, если хочешь!