Объединить наблюдаемые ActivatedRoute с наблюдаемыми из запросов API

#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] вместо just data , код может быть немного более читаемым.)

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 , и теперь это работает хорошо. Спасибо, сэр!