2016-05-02 2 views
13

Для веб-приложения, написанного с помощью Angular2 в TypeScript, мне нужно работать с RxJs Observable s.
Как я никогда раньше не использовал rxjs, и я новичок в реактивном программировании в целом, у меня иногда возникают трудности с поиском правильного пути для выполнения определенных задач.
Теперь я столкнулся с проблемой. где мне нужно преобразовать Array<Observable<T>> в Observable<Array<T>>.
Я попытаюсь объяснить это на примере:
- У меня есть Observable, который дает мне список Users (Observable<Array<User>>)
- The User -класс имеет функцию getPosts возвращающую Observable<Array<Post>>.
- Мне нужно сопоставить Observable<Array<User>> с Observable<Array<Post>>, чтобы оценить все Post s внутри функции onNext.RxJs Массив наблюдаемого массива

можно легко сопоставить с Observable<Array<User>> с Observable<Array<Observable<Array<Post>>>> использованием
map((result : Array<User>) => result.map((user : User) => user.getPosts()))
анс можно расплющить в Array<Array<Post>> в Array<Post>.
Однако я просто не могу найти правильный путь, чтобы картированию Observable<Array<Observable<Array<Post>>>> в качестве Observable<Array<Array<Post>>>
До сих пор я использовал функцию combineLatest вместе с flatMap.
Мне казалось, что это работает, и редактор, который я использовал (редактор Atom), не обнаружил ошибок. Однако теперь я использую Netbeans, который показывает мне ошибку в этом коде. Также компиляция кода с использованием «tsc» приводит к ошибкам.
Внешний вид, как это:

Argument of type '(result: Post[]) => void' is not assignable to parameter of type 'NextObserver<[Observable<Post>]> | ErrorObserver<[Observable<Post>]> | CompletionObserver<[...'. 
Type '(result: Post[]) => void' is not assignable to type '(value: [Observable<Post>]) => void'. 

Так что мой вопрос:
Как можно "сгладить" в Array из Observables в Array?

+0

Что соответствует методу 'getPosts'? Загружает ли он сообщения определенного пользователя? –

ответ

22

Оператор flatMap позволяет это сделать. Я не совсем понимаю, что вы пытаетесь сделать, но я попытаюсь дать ответ ...

Если вы хотите загрузить все

getPostsPerUser() { 
    return this.http.get('/users') 
    .map(res => res.json()) 
    .flatMap((result : Array<User>) => { 
     return Observable.forkJoin(
     result.map((user : User) => user.getPosts()); 
    }); 
} 

Observable.forkJoin позволяет ждать все наблюдаемые иметь полученные данные.

Код выше предполагает, что user.getPosts() возвращает наблюдаемым ...

При этом, вы получите массив массив сообщений:

this.getPostsPerUser().subscribe(result => { 
    var postsUser1 = result[0]; 
    var postsUser2 = result[1]; 
    (...) 
}); 
+1

Да, 'getPosts()' возвращает 'Observable >'. Поэтому я предполагаю, что это то, что я ищу. Я попробую это как можно скорее и сообщит, если это сработает.Спасибо – Springrbua

+0

Работает отлично. Я только шляпу, чтобы заменить 'combLatest' на' forkJoin'. Большое спасибо! – Springrbua

3

Вы можете использовать функцию применить на методе rxjs вы хотите, как это:

const source1 = Rx.Observable.interval(100) 
 
    .map(function (i) { return 'First: ' + i; }); 
 

 
const source2 = Rx.Observable.interval(150) 
 
    .map(function (i) { return 'Second: ' + i; }); 
 

 
const observablesArray = [source1, source2]; 
 

 
const sources = Rx.Observable.combineLatest 
 
.apply(this, observablesArray).take(4) 
 

 
// or 
 

 
const sources = Rx.Observable 
 
       .combineLatest(...observablesArray) 
 
       .take(4) 
 

 
sources.subscribe(
 
    (response) => { 
 
    console.log(response); 
 
    } 
 
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.1/Rx.min.js"></script>

+0

Я думаю, это должно сработать, но сейчас я буду придерживаться 'forkJoin'. – Springrbua

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