#angular #typescript #rxjs
#angular #typescript #rxjs
Вопрос:
Я пытаюсь объединить два наблюдаемых, используя forkJoin
или combineLatest
(мои два варианта до сих пор). Один наблюдаемый — из данных ActivatedRoute ( Observable<Data>
), а другой — вызов API ( Observable<Project>
).
Изначально эти два были каскадированы, и все работало нормально. Но я подумал, что это можно улучшить, объединив два наблюдаемых. Я знаю, что наблюдаемый из активированного маршрута не завершен, и он будет запускаться каждый раз, когда пользователь перемещается по приложению. Вторая наблюдаемая завершается при получении ответа. forkJoin
Работает со вторым типом наблюдаемых (те, которые завершены) и combineLatest
работает с теми, которые не завершены, принимая их последние значения.
Есть ли способ объединить эти два или каскадный подход является лучшим способом? Спасибо!
РЕДАКТИРОВАТЬ: я обновил код, чтобы исправить некоторые небольшие проблемы и добавить деконструкцию массива.
Однако я обнаружил, что при обновлении приложения на текущей странице RouteData является пустым объектом, но если я добавлю точку останова (на вкладке DevTools Source ), где установлены RouteData, это работает. Или, если я перейду к компоненту, который задает данные маршрута, он все равно работает. Итак, я предполагаю, что небольшая задержка позволит заполнить текущие RouteData? Но почему он не запускается снова, когда фактические данные размещаются на маршруте? Надеюсь, это не слишком сбивает с толку
Позже отредактируйте: у меня есть 2 страницы с их соответствующими компонентами: Управление активами (AssetManagementComponent) и Управление проектами (ProjectManagementComponent). Компонент проекта является дочерним компонентом компонента активов. Когда компонент актива инициализируется, я получаю некоторые данные из API и помещаю их в route.data
. Теперь, когда компонент проекта (дочерний) загружен, я хочу получить эти данные маршрута и некоторые дополнительные данные, связанные с конкретным проектом, из API.
Проблема в том, что если я обновлю страницу управления проектом, приведенный выше код routeData
станет просто пустым объектом {}
. Но если я перейду к управлению активами, а затем к управлению проектами, routeData
будут содержаться правильные данные.
Я пытался отладить эту проблему с помощью DevTools, и если я помещу точки останова в каждую функцию ngOnInit(), она будет корректной routeData
, даже если я напрямую обновлю приложение в ProjectManagement
Обновить:
Это окончательная и рабочая версия: Добавление фильтра к наблюдаемым данным маршрута исправило это, кажется, что он срабатывал один раз с пустым объектом, а затем с допустимым объектом.
Спасибо всем за ваши комментарии, я узнал новые вещи и хорошие практики! Хорошего дня!
Комментарии:
1. В чем проблема с тем, что у вас есть? Вы можете объединить их с параметрами, которые вы перечислили выше. Проблема с синхронизацией или что-то в этом роде?
2. При
combineLatest
этом каждый раз, когда генерируется какая-либо из объединенных наблюдаемых, она генерирует значение из всех наблюдаемых. ЕслиgetProjectDetails
наблюдаемый объект генерируется только один раз,combineLatest
он сохранит переданное значение и повторно генерирует его каждый раз, когда генерируется route Observable. Я часто использую этотcombineLatest
метод. (Кстати, если вы используете деструктурирование массива [RouteData, project] вместо justdata
, код может быть немного более читаемым.)3. Есть ли способ объединить эти два — но вы уже объединяете их с помощью combineLatest . Ваш подход уже элегантен. Я бы хотел еще кое-что добавить к комментарию @DeborahK. Все исходные наблюдаемые должны быть отправлены хотя бы один раз, прежде чем
combineLatest
они начнут отправляться. Итак, если вы думаете, что некоторые из выбросов одного из наблюдаемых пропущены, вы можете передатьstartWith
оператор наблюдаемому, который начинает излучать поздно, чтобы запустить запускcombineLatest
.4. Действительно, я пропустил проблему . Итак, объединение работает, но первые данные отсутствуют, наблюдаемый маршрут просто возвращает пустой объект
{}
. Также большое спасибо за советы по деконструкции, это красиво5. Также есть ошибка, вызывающая
processRelatedEntities
функцию сthis.project
перед установкойthis.project
, только что обнаружил, что
Ответ №1:
Если я правильно понимаю, то, как я бы поступил, это воспользоваться картой слияния. Похоже, что происходит, когда ваши подписки на activeRoute попадают в первый раз, когда они обновляются, они пусты, а затем он получает данные и отправляет вторую.
Этот подход отфильтрует все параметры маршрута, у которых нет ресурса, как только он пройдет фильтр, мы объединяем его с этим в следующий запрос, чтобы мы могли передать его на конечную карту, где у вас есть оба значения, которые всегда должны заполняться, если этот код достигнут.
Так что что-то подобное может работать лучше для вас.
this.route.parent.data.pipe(
filter(routeData => routeData amp;amp; routeData.asset), //make sure route data is there
mergeMap(routeData =>{
return this.projectService.getProjectDetails(projectId).pipe.map(project =>{
return {routeData, project}
})
}),
map(data => {
// now you should have access to data.routeDate and data.project
})
).subscribe()
Надеюсь, это поможет routeParams может быть сложно, когда вам нужно это значение для выполнения другого вызова.
Я думаю, что код правильный, но его поздно, и я просто вспоминал это из памяти (и Google) ха-ха
Комментарии:
1. Это
filter(routeData => routeData amp;amp; routeData.asset)
была недостающая часть. Я добавил это вroute.data
, и теперь это работает хорошо. Спасибо, сэр!