2016-10-07 5 views
0

Я пытаюсь получить конкретную Пункт, например, { key: "321" } из ngrx/store на основе параметров маршрута. Я получил это работает так:Свести наблюдаемом

this.route.params 
    .map((params: any) => params.key) 

    .mergeMap((key: string) => { 

    return this.store.select(state => state.items) 

     .mergeMap((items: Observable<any[]>) => items) 

     // .do(item => console.log(item, key)) 

     .filter((item: any) => item.key === key); 
    }) 
    .take(1) 
    .subscribe(console.log); 

где state.items представляет собой массив объектов, как: [ {key: "1"}, {key: "2"}, ...], который заполняет в течение долгого времени.

Мне интересно, есть ли лучший способ для этого?

Кроме того, почему я получаю один и тот же элемент несколько (state.items.length) раз до .take(1)?

+0

Вы хотите, чтобы принести несколько элементов из массива элемента в вашем магазине? Если это так, ваш код можно оптимизировать. – KwintenP

+0

@KwintenP Мне нужно получить элемент из списка по значению определенного свойства. Значение url '/ items/123' равно ** 123 **, а свойство - ** **, например. – Sasxa

ответ

1

Код довольно хорош уже, но внутренний mergeMap не нужен. Фильтр должен быть действительно картой, если я правильно понимаю. Вы получаете массив элементов в инструкции store.select, и в вашем фильтре вы обрабатываете один элемент за раз. Это не должно работать, так как это массив, над которым вы работаете. Используя карту, мы можем получить массив элементов в качестве входных данных и вернуть элемент, который на самом деле тот, который мы ищем.

this.route.params 
    .map((params: any) => params.key) 
    .mergeMap((key: string) => { 
     return this.store.select(state => state.items) 

     // no need for this mergeMap 
     //.mergeMap((items: Observable<any[]>) => items) 

     // map will actually get an array of items as input here 
     // we want to get the element from the array matching 
     // the key from the route param and return the first element 
     // => [0] since there should be only one 
     .map((item: any[]) => items.filter((item) => item.key === key)[0]; 
}) 
.take(1) 
.subscribe(console.log); 

Jsbin с издевались рабочий пример: http://jsbin.com/sihina/7/edit?js,console

+0

Да, функциональность такая же, но ваш способ может быть более эффективным, так как 'mergeMap()' преобразует наблюдаемый массив в массив наблюдаемых, в то время как карта + фильтр работает на * чистом массиве * ... – Sasxa

+0

MergeMap действительно не делает то, что вы описываете, если я не ошибаюсь. MergeMap будет выполнять функцию для каждого элемента наблюдаемого. Результат этой функции должен быть наблюдаемым, который сглаживается оператором mergeMap. – KwintenP