#angular #rxjs
Вопрос:
Я работаю над приложением, в котором есть раздел «Избранное». Я извлекаю два источника данных: один из файла const, который я экспортирую как наблюдатель(observerA$), и один из базы данных, которая содержит только идентификаторы, которые были выбраны(observerB$), и оба работают по назначению. Я хотел бы использовать сохраненные идентификаторы из observerB$, чтобы пометить логическое значение в observerA$
ObserverA$ содержит всю информацию, которую я использую для заполнения пользовательского интерфейса. Интерфейс для observerA
{
title: string,
id: number,
page: string,
subcategory: string,
favorite?: boolean
}
observerB$ содержит идентификаторы для избранных элементов
Интерфейс для наблюдателя$
{
(some unrelated fields)
id: number
}
Я заставляю его работать, изменяя массив внутри моего компонента, но так как он используется в нескольких компонентах, я бы подписался на observerA$, используя asyncpipe, чтобы получать обновления без необходимости использовать массив машинописи
Комментарии:
1. Можете ли вы создать Стакблитц ?
2. Нам понадобится немного больше, чтобы продолжить, потому что то, как вы работаете с двумя массивами, зависит от особенностей того, чего вы пытаетесь достичь. Если вам нужны некоторые общие идеи работы с декларативным подходом, ознакомьтесь с первыми 30 минутами этого видео: youtube.com/watch?v=iSsch65n8Yw
3. Если ObserverA$ содержит всю информацию, которую я использую для заполнения пользовательского интерфейса, то, похоже, вы показываете только один заголовок? Это правда?
4. Да, и извините за недостаток информации, я новичок в angular после работы в knockoutjs в течение последних 3 лет, поэтому я не уверен во всей терминологии. По сути, ObserverA$ содержит всю необходимую информацию для пользовательского интерфейса. Я хочу подписаться на этого наблюдателя, чтобы заполнить пользовательский интерфейс, но мне нужно изменить логическое значение «избранное», сопоставив идентификаторы из observerB$. Я рассмотрю возможность использования stackblitz для получения дополнительной информации. В настоящее время я пытаюсь использовать .map для достижения этой цели
Ответ №1:
Это звучит так, как будто вы пытаетесь составить наблюдаемое из двух наблюдаемых источников. Давайте назовем ваши два источника наблюдаемыми item$
и favoriteIds$
для простоты.
Вы можете определить свою составленную наблюдаемую (назовите ее itemWithFavoriteProperty$
просто для краткости) следующим образом:
const itemWithFavoriteProperty$ = item$.pipe(
switchMap(item => favoriteIds$.pipe(
map(favoriteIds => favoriteIds.some(id => id === item.id)),
map(favorite => ({...item, favorite}))
))
);
Если вы не знакомы с switchMap
ним , он в основном подписывается на наблюдаемый источник и испускает свои выбросы. Таким образом, всякий item$
раз, когда эмиссирует, switchMap
будет подписываться favoriteIds$
и выдавать массив идентификаторов (в любое время, когда он меняется), который мы затем сопоставляем:
- сначала к логическому значению, указывающему, находится ли элемент в избранном массиве
- затем к копии, выданной
item
с приложениемfavorite
свойства.
Так itemWithFavoriteProperty$
будет излучать в любое время item$
или когда favoriteIds$
будет излучать. Однако на самом деле мы не хотим выдавать, если favorite
логическое значение не изменилось, поэтому мы можем использовать distinctUntilChanged
:
const itemWithFavoriteProperty$ = item$.pipe(
switchMap(item => favoriteIds$.pipe(
map(favoriteIds => favoriteIds.some(id => id === item.id)),
distinctUntilChanged(),
map(favorite => ({...item, favorite}))
))
);
Вот стекблитц, с которым вы можете поиграть.
Комментарии:
1. Большое вам спасибо за помощь. Похоже, это правильное направление для меня, я действительно ценю это. Единственная проблема, с которой я сталкиваюсь прямо сейчас, заключается в том, что я получаю ошибку после .some, в ней говорится, что идентификатор не существует в элементе [], поэтому я думаю, что мне нужно распаковать этот массив, прежде чем он заработает, но это огромная помощь