#angular #rxjs #observable
#угловой #rxjs #наблюдаемый
Вопрос:
В форме я хочу добавить книгу.
Пользователь вручную вводит имя автора. Когда пользователь отправляет форму, он должен сначала проверить, существует ли автор :
- если нет, это создает автора
- Если он уже существует, он просто извлекает информацию об авторах (id)
- Затем он добавляет книгу с идентификатором автора
Я думаю, что смогу заставить его работать с :
formSubmit() {
this.authorService.getByName(this.authorName).subscribe(author => {
// Author exists
if (author.id) {
this.book.author = author;
this.bookService.add(this.book).subscribe(() => {
// Book added
});
} else {
const authorObj: AuthorInterface = {
fullName = this.authorName;
}
this.authorService.add(authorObj); subscribe(author => {
this.book.author = author;
this.bookService.add(this.book).subscribe(() => {
// Book added
});
})
}
});
}
Но это действительно ужасно, я уверен, что смогу сделать его чище, rxjs
но не могу найти решение. Я немного смущен тем, как использовать все эти функции.
Я буду признателен за некоторую помощь. Большое спасибо 🙂
Комментарии:
1. Некоторые вопросы: Цель состоит в том, чтобы сохранить автора в объекте book? Если вы запрашиваете несуществующего автора по имени, он все равно возвращает объект author, но без идентификатора? Зачем вы добавляете книгу, если «Автор существует»? У меня есть представление о ваших требованиях, и, насколько я вижу проблему, вы можете решить ее с помощью одной подписки во время выполнения. Поэтому мне нужны ответы на мои три вопроса.
2. Цель состоит в том, чтобы сохранить книгу с автором, но если автор уже добавлен, я хочу извлечь его и добавить в книгу. На самом деле, это пример, над которым я не работаю над книгами и автором, но мы можем представить, что если пользователь не существует, API возвращает и пустой объект (я использую платформу API для возврата). Если автор существует, я могу захотеть добавить новую книгу, которую он только что написал 🙂
Ответ №1:
Вы можете использовать switchMap. Этот оператор подписывается на другую наблюдаемую, которую вы передаете ему, и выводит ее результат.
this.authorService.getByName(this.authorName)
.pipe(
switchMap(author => {
if (author.id) {
this.book.author = author;
return this.bookService.add(this.book).pipe(...);
}
return this.authorService.add(authorObj).pipe(
switchMap(author => ...)
);
})
)
.subscribe();
Ответ №2:
если это большое наблюдаемое значение (много передаваемых значений), вам лучше остаться с if else
this.authorService
.getByName(this.authorName)
.pipe(
mergeMap((author: any) => {
if (author.id) {
this.book.author = author;
return this.bookService.add(this.book).pipe(
tap(() => {
console.log("book added");
})
);
} else {
const authorObj: AuthorInterface = {
fullName: this.authorName
};
return this.authorService.add(authorObj).pipe(
mergeMap((author: any) => {
this.book.author = author;
return this.bookService.add(this.book).pipe(
tap(() => {
console.log("book added");
})
);
})
);
}
})
)
.subscribe(() => console.log("job done"));
в качестве альтернативы вы можете сделать это:
const firstObservable = this.authorService.getByName(this.authorName).pipe(
filter((author: any) => author.id != null),
mergeMap(author => {
this.book.author = author;
return this.bookService.add(this.book).pipe(
tap(() => {
console.log("book added");
})
);
})
);
const secondObservable = this.authorService.getByName(this.authorName).pipe(
filter((author: any) => author.id == null),
mergeMap((author: any) => {
const authorObj: AuthorInterface = {
fullName: this.authorName
};
return this.authorService.add(authorObj).pipe(
mergeMap((author: any) => {
this.book.author = author;
return this.bookService.add(this.book).pipe(
tap(() => {
console.log("book added");
})
);
})
);
})
);
merge(firstObservable, secondObservable).subscribe(author =>
console.log("job done")
);