Используйте подписку внутри распознавателя маршрутов - PullRequest
2 голосов
/ 23 октября 2019

Я хочу запросить у службы некоторые данные, чтобы разрешить определителю действий выполнить определенное действие.

Данные, которые должны быть возвращены службой, не являются данными, которые будут использоватьсякомпонент после разрешения маршрута, который является явным использованием распознавателя и объясняет, почему распознаватель должен возвращать Observable.

Для чего мне действительно нужны данные, возвращаемые службой, - это выбор между несколькимивозможные действия до того, как маршрут будет решен вообще.

Почему я попал в эту ситуацию?

Я в том случае, когда верхний URL с параметром slugможет потребоваться отрисовка отдельных компонентов.

Пример :

example.com / what-post-slug -> необходимо загрузить PostComponent
example.com/other-page-slug -> необходимо загрузить PageComponent
example.com/new-slug-for-random-post -> необходимо загрузить PostComponent
...

Почему бы мне просто не указать префикс маршрута?

Потому что я не могу. Я создаю тему для WordPress и разрешаю похожие ссылки для постов и страниц. См. этот вопрос для получения более подробной информации.

Что на самом деле делает мой распознаватель?

Я покажу только частичный код, чтобы сделать его понятным:

resolve(route: ActivatedRouteSnapshot): Observable<any>|any{
   this.wprestNoAuthSrv.getPermalinkStructure()
       .pipe(takeUntil(this.unsubscribeOnDestroy))
       .subscribe(
       // ... check httpResponse and decide where to go
          this.router.navigate(route, { skipLocationChange: true });
       )
}

Из-за того, что я подписываюсь внутри распознавателя, компонент, связанный с разрешаемым маршрутом, загружается перед навигацией ().

Это приводит к оченьуродливый эффект навигации.

Вопрос :

Как я могу предотвратить это, продолжая использовать это подозрение?

Я действительно этого хочукомпонент никогда не загружается, потому что всегда будет происходить navigate().

Если вы понимаете, я помещаю { skipLocationChange: true } в router.navigate(), потому что я хочу, чтобы пользователь оставил путь в браузере.

Я понимаю, что может показаться, что я неправильно использую систему маршрутизации Angular, но я хочу достичь этого результата.

Этот вопрос не о том, что я хочу загружать различные компоненты динамически (для этого яопубликовал приведенный выше связанный вопрос) .

Этот вопрос касается выбранного подхода, который работает, но с недостатком, которого я хотел бы избежать.

AnИдея, которая работает :

Эта идея работает, но, возможно, вы знаете лучшее решение. Если я создаю observabe и возвращаю его в методе resolve(), я могу заставить распознаватель ждать, и перенаправление будет уже выполнено к тому времени, когда оно завершится.

return Observable.create(observer => {
  setTimeout(() => {
    observer.next("Finished");
    observer.complete();
  }, 5000);
});

Конечно, этобольшая ложь и не очень приятно. И хотя он работает отлично, мне нужно знать, очень ли это плохо или есть лучшая альтернатива.

1 Ответ

3 голосов
/ 23 октября 2019

Похоже, вы пытаетесь перенаправить внутри распознавателя, и подписка внутри Observable никогда не была хорошей идеей. Это должно соответствовать вашим ожиданиям:

resolve(route: ActivatedRouteSnapshot): Observable<any>|any{
   return this.wprestNoAuthSrv.getPermalinkStructure().pipe(
     takeUntil(this.unsubscribeOnDestroy),
     mergeMap(httpResponse => {
       // ... check httpResponse and decide where to go
       this.router.navigate(route, { skipLocationChange: true });
       return EMPTY;
     })
   );
}
...