Как вы показали в своем вопросе, если / то логика с наблюдаемыми может быть хитрой.Здесь есть хорошая дискуссия здесь .
У вас уже было несколько ответов, которые могли бы работать при определенных условиях, и я бы вылетел и оставил вас в умелых рукахФан или Джеффри, но я был заинтригован комментарием, который вы сделали к одному ответу: «Что произойдет, если я добавлю больше условий?».Это заинтересовало меня, и поэтому я хотел найти шаблон, который можно было бы заметить / сделать функциональным, понятным и легко расширяемым, если позже вы решите добавить дополнительные условия.Хороший вопрос заставляет меня задуматься, и вы, конечно, сделали это.:)
Я попытался применить шаблон, который был предложен в статье, которую я связал выше, к вашей проблеме, и код ниже - то, что я придумал.Как я упоминал в комментарии к вашему первоначальному вопросу выше, я не уверен на 100%, что вы намереваетесь обновить контакт, когда пользователь НЕ является новым пользователем, но сейчас я предположил, что вы это делаете.Отказ от ответственности: я не проводил строгих проверок, таких как создание Stackblitz и создание различных тестовых случаев, хотя именно так я обычно хотел бы ответить на такой вопрос, поэтому я приношу свои извинения за любые ошибки или непредвиденные последствия в приведенном ниже коде.Увы, выходной зовет.;)
В этом паттерне в статье предлагается создавать ветви для всех возможных путей через логику if / then.Я придумал две основные ветви, которые привели бы к вызову updateContact ().Обратите внимание, что с этим шаблоном легко добавить tap()
в любую из ветвей, чтобы при необходимости выполнить дополнительную работу.Если я пропустил ветку, которую вы хотите добавить, ее также легко добавить.
Сердцем этого шаблона является merge () в конце.Это создает одну наблюдаемую область, которая объединяет две переданные. Если любая из них завершается, то подписка будет выполняться и запускать updateContact()
.В этом случае они никогда не будут выполнены оба из-за фильтра isNewUser()
, гарантирующего, что будет активен только один, но если вы примените этот шаблон в другом месте, вы можете добавить take(1)
, если вам нужен только первый асинхронный, который 'wins '.
Я также показываю подписку и отписку, так как считаю, что это лучшая практика.
onSomeEventSub : Subscription; // component scope variable to add to later unsubscribe with
onSomeEvent() {
const contact: IContact = {
...this.userForm.value
};
// define duplicateUserSearch$ now for easier readability below
const duplicateUserSearch$: Observable<boolean> =
this.userService.duplicateUserSearch(contact.email, contact.userName).pipe(
map(result => (result.result === '')));
// First, create a shareable source for eventual merge of all branches.
// of(0) is completely arbitrary. It would be more interesting to tie
// this to the original event, but that wasn't part of the question. :)
const source$ = of(0).pipe(
share() // same observable will have multiple observers
);
// branch 1 is for when the user is a new user and duplicate logic asserts
const isNewUserAndIsDupe$ = source$.pipe(
filter(() => isNewUser()),
mergeMap(() => duplicateUserSearch$),
filter(res => res)
);
// branch 2 is when the user is NOT a new user
const isNotNewUser$ = source$.pipe(
filter(() => !isNewUser())
);
// and finally the merge that pulls this all together and subscribes
this.onSomeEventSub = merge(isNewUserAndIsDupe$, isNotNewUser$).pipe(
mergeMap(() => this.userService.updateContact(contact))
).subscribe(res => this.activeModal.close(res));
}
ngOnDestroy() {
if (this.onSomeEventSub) this.onSomeEventSub.unsubscribe();
}