Лучшая практика извлечения параметров и queryParams в Angular 2

Я пытаюсь понять способ создания маршрута, с некоторой информацией в нем параметры URL.

Это мой маршрут (app.routes.ts):

{path: 'results/:id', component: MyResultsComponent},

Вот как я перемещаюсь по маршруту:

goToResultsPage(query: string) {
this.router.navigate(['results', query], { queryParams: { pageSize: 20 } });}

Как вы можете видеть, у меня также есть параметр запроса. Мне было интересно, какой лучший и самый чистый способ получить это в моем MyResultsComponent. Прямо сейчас у меня есть вложенная структура subscribe:

ngOnInit() {
    this.route
      .params
      .subscribe(params => {
        this.query = params['id'];
        this.route
          .queryParams
          .subscribe(queryParams => {
            this.offset = queryParams['pageSize'];
            #find entries this.entryService.findEntries(this.query, this.pageSize);
      });
    });
  }

Затем я хочу передать эти параметры в мой EntryService, который возвращает найденные записи.

Ответ 1

Как насчет использования forkJoin?

ForkJoin позволяет вам присоединиться к двум наблюдаемым и ждать ответа обоих. Вы можете увидеть документацию здесь и подробнее об этом здесь.

Что касается вашего кода, он будет выглядеть примерно так:

ngOnInit() {
    Observable.forkJoin(this.route.params, this.route.queryParams).subscribe(bothParams => {
        // bothParams is an array, on the first index we have the router.params 
        // on the second index we have the queryParams
        this.query = bothParams[0].query;
        this.pageSize = bothParams[0].pageSize;
        this.entryService.findEntries(this.query, this.pageSize);
    });
  }

Вам может потребоваться добавить импорт:

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/forkJoin';

Ответ 2

Observable.combineLatest - это решение в этой ситуации, не так ли?

Observable
  .combineLatest(
    this.route.params,
    this.route.queryParams,
    (params: any, queryParams: any) => {
      return {
        id: +params.id,
        pageSize: queryParams.pageSize ? +queryParams.pageSize: null
      }
    })
  .subscribe(bothParams => {
    this.id = bothParams.id;
    this.pageSize = bothParams.pageSize;
  });

Ответ 3

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

Не тестировался (только с верхушки головы)

ngOnInit() {
    this.route
      .params
      .subscribe(params => {
        this.query = params['id'];
        this.offset = this.route.snapshot.queryParams['pageSize'];
        # find entries this.entryService.findEntries(this.query, this.pageSize);
      });
    });
  }

Ответ 4

Недавно я столкнулся с этой дилеммой, и лучшее решение, удовлетворяющее моим потребностям, которое я нашел, - это использовать Observable.merge.

Использование моментального снимка не очень хорошо, если вы хотите смотреть изменения из params queryParams внутри одного и того же компонента (например, поиск с фильтрами).

Observable.forkJoin имеет ограничение на то, что оба наблюдаемых должны запускаться, чтобы работать, поэтому, если у вас есть сценарий, в котором могут быть изменения в параметрах или в параметрах queryParams, но необязательно в обоих случаях, forkJoin не будет использовать вас.

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

Вот пример:

Observable.merge(
  this.route.params.map(params => this.handleParams(params)),
  this.route.queryParams.map(queryParams => this.handleQueryParams(queryParams))
)
.subscribe(
  () => this.onParamsOrQueryParamsChange()
);

Ответ 5

Вы можете попробовать это:

setTimeout(() => {
  this.route.queryParams
    .subscribe((params: Params) => {
      console.log('PARAMS',params);
      }
    });
},0);