2016-11-11 9 views
1

У меня есть следующий код:Подписаться на эмиттер событий, когда массив загружен

this.itemsService.getItems() 
    .subscribe(i => this.items = i); 

Но, пользователь может выбрать тип элемента, поэтому у меня есть эмиттер событий для этого:

this.typeofitems.selectedType.subscribe(type => this.type = type); 

и хорошо работает.

Теперь я хочу отфильтровать список предметов this.items с filter function. Проблема заключается в том, я не знаю, когда загрузка элементов завершена, Altough если я положил бревно в подписке:

this.itemsService.getItems() 
    .subscribe(i => {this.items = i; console.log("completed");}); 

это указывает мне, что это закончено. Поэтому я пробовал:

this.itemsService.getItems() 
    .subscribe(i => { 
     this.items = i; 
     this.typeofitems.selectedType.subscribe(type => { 
      this.type = type; 
      this.filterByType(); 
     }); 
    }); 

filterByType() { 
    this.itemsfilteredByType = this.items.filter(i => i.type === this.type) 
} 

Но он не работает. Поэтому я думаю, что не могу подписаться внутри подписи. Как я могу это достичь?

ответ

2

Обратите внимание, что вы используете = вместо == в обратном вызове filter(), поэтому убедитесь, что это не проблема.

Во всяком случае, вы можете использовать оператор combineLatest(), который излучает значение, каждый раз, когда какой-либо из ее источников испускать значение (в то время как, по меньшей мере, одно значение из каждого источника должен быть испускается):

function getItems() { 
    return Observable.of([{type: 1, val: 345}, {type: 2, val: 107}, {type: 1, val: 926}, {type: 2, val: 456} ]); 
} 

let typeOfItems = new Subject(); 

Observable.combineLatest(getItems(), typeOfItems) 
    .subscribe(vals => { 
    let [items, typeOfItem] = vals; 

    let results = items.filter(i => i.type == typeOfItem); 
    console.log(results); 
    }); 

typeOfItems.next(2); 

Это фильтрует детали type == 2 и выводит на консоль:

[[object Object] { 
    type: 2, 
    val: 107 
}, [object Object] { 
    type: 2, 
    val: 456 
}] 

Он работает благодаря combineLatest(), который первым получает все детали, а затем я говорю это, чтобы фильтровать их по type == 2 с помощью typeOfItems.next(2);, который инициирует вызов к обратный вызов для combineLatest(), который использует Array.filter() для фактического фильтрации и печати фильтрованных элементов (обратите внимание, что это Array.fitler(), а не Observable.filter()).

Смотреть демо: https://jsbin.com/nenosiy/5/edit?js,console

Btw, конечно, вы можете subscribe() внутри другого subscribe() обратного вызова. Просто помните, что вам нужно вручную отказаться от подписки на предыдущие подписки.

См очень похожий вопрос: Dynamically filtering rxjs stream

+0

незадача: при изменении typeOfItems, он будет звонить в GetItems снова? – FacundoGFlores

+0

@FacundoGFlores Почему бы вам не попробовать? Просто добавьте 'typeOfItems.next (1);' в конце и посмотрите, что произойдет. – martin

Смежные вопросы