#angular #rxjs #observable #reactive-programming
#angular #rxjs #наблюдаемый #реактивное программирование
Вопрос:
У меня есть «вложенные» запросы, создание команды и загрузка аватара команды, где второй зависит от первого и должен быть отправлен, только если аватар не равен нулю (я уже сделал это с помощью оператора фильтра). Что мне нужно сейчас, так это получить доступ к обоим ответам в методе подписки.
this.team.createTeam(teamRequest)
.pipe(
filter(() => avatar),
flatMap(next => this.team.uploadLogo(avatar, next.body.uuid)
).subscribe(responses => {
// so, I want response from both createTeam and uploadLogo in responses
});
Ответ №1:
Вы могли бы передать map
оператор во внутренний запрос и отправить оба ответа. Попробуйте следующее
this.team.createTeam(teamRequest)
.pipe(
filter(() => avatar),
flatMap(next =>
this.team.uploadLogo(avatar, next.body.uuid).pipe(
map(res => ({ avatar: res, team: next }))
)
)
).subscribe(responses => {
// responses.avatar: response from `this.team.uploadLogo(avatar, next.body.uuid)`
// responses.team: response from `this.team.createTeam(teamRequest)`
});
Я вернул объект для иллюстрации. Вы можете вернуть его в любой форме в соответствии с вашими требованиями. Например. в виде массива map(res => [ next, res ]))
.
Обновление: iif
функция вместо filter
оператора
Если вы все еще хотите подписаться на источник, наблюдаемый при сбое filter
условия, самый быстрый способ, который я мог придумать, — это отказаться от filter
оператора и вместо этого использовать iif
функцию. Попробуйте следующее
const upload = (avatar, team): Observable<any> => {
return this.team.uploadLogo(avatar, next.body.uuid).pipe(
map(res => ({ avatar: avatar, team: team }))
);
};
iif(() =>
!!avatar,
this.team.createTeam(teamRequest).pipe(flatMap(next => upload(avatar, next.body.uuid))),
this.team.createTeam(teamRequest)
).subscribe(
responses => {
// if `avatar` is null
// responses: response from `this.team.createTeam(teamRequest)`
// or
// if `avatar` is non-null
// responses.avatar: response from `this.team.uploadLogo(avatar, next.body.uuid)`
// responses.team: response from `this.team.createTeam(teamRequest)`
}
);
Обновление: проверьте avatar
внутри flatMap
Как предложил @bryan60, вот более чистый код, который не использует ни filter
ни iif
. Но скорее проверяет avatar
внутри flatMap
и возвращает of(next)
значение null.
this.team.createTeam(teamRequest).pipe(
flatMap(next => {
if (!!avatar) {
return this.team.uploadLogo(avatar, next.body.uuid).pipe(
map(res => ({ avatar: res, team: next }))
);
}
return of(next);
})
).subscribe(responses => {
// if `avatar` is null
// responses: response from `this.team.createTeam(teamRequest)`
// or
// if `avatar` is non-null
// responses.avatar: response from `this.team.uploadLogo(avatar, next.body.uuid)`
// responses.team: response from `this.team.createTeam(teamRequest)`
});
Комментарии:
1. Псевдоним
flatMap
устарел, лучше использоватьmergeMap
.2. Кстати, если аватар равен нулю и фильтр не работает, мне все равно нужно получить ответ от createTeam. Как я могу это сделать??
3. Да, я тоже думал об этом. Спасибо вам еще раз.
4. удалите условие фильтра.
5.
flatMap
в коде упоминается устаревание github.com/ReactiveX/rxjs/blob / … мой локальный vs-код также отображает это сообщение.