Условные наблюдаемые с forkJoin - PullRequest
0 голосов
/ 12 сентября 2018

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

let observables: Observable<any>[] = [];

observables.push(this.taskService.getStep(this.housingTransactionId, this.task.stageReferenceId, this.task.stepReferenceId));

if (this.task.associatedChatThreadId) {
    observables.push(this.messageHubService.getChatThread(this.housingTransactionId, this.task.associatedChatThreadId));
}

if (this.task.associatedDocuments && this.task.associatedDocuments.length > 0) {
    this.task.associatedDocuments.forEach(documentId => {
        observables.push(this.documentHubService.getDocumentProperties(this.housingTransactionId, documentId));
    });
}

Observable.forkJoin(observables)
    .subscribe(([step, chatThread, ...documents]) => {

        this.step = step;           
        this.chatThread = chatThread;           
        this.documents = documents;

        this.isPageLoading = false;

    }, error => {
        this.isPageLoading = false;
        console.log(error);
    });

Проблема, которую я получаю, состоит в том, что если у меня нет this.task.associatedChatThreadId, то наблюдаемое не добавляется в список, и когда выполняется forkJoin, ...documents находятся в положении chatThread свойство в методе подписки (ну, первый документ!).

Есть ли способ обеспечить позиционирование ответов от forkJoin? Или я / я могу использовать другой подход?

Ответы [ 3 ]

0 голосов
/ 12 сентября 2018

Другим подходом было бы не использовать folkJoin, а подписываться отдельно.В то же время, сделайте isPageLoading объектом BehaviorSubject, который подсчитывает, сколько асинхронных запросов у вас есть в данный момент.Каждый раз, когда вы делаете запрос, вы можете иметь isPageLoading.next (1) и isPageLoading.next (-1), когда вы завершаете запрос.

0 голосов
/ 13 сентября 2018

Вы можете создать вспомогательную функцию, которая принимает объект со строковыми ключами и наблюдаемыми значениями и возвращает наблюдаемую, которая будет испускать объект с теми же ключами, но с результирующими значениями вместо наблюдаемых в качестве значений.

Я бы не сказал, что это более чистая версия, чем использование (null), как предложено martin, но это может быть альтернативой.

function namedForkJoin(map: {[key: string]: Observable<any>}): Observable<{[key: string]: any}> {
    // Get object keys
    const keys = Object.keys(map);

    // If our observable map is empty, we want to return an empty object
    if (keys.length === 0) {
        return of({});
    }


    // Create a fork join operation out of the available observables
    const forkJoin$ = Observable.forkJoin(...keys.map(key => map[key]))

    return forkJoin$
        .map(array => {
            const result = {};
            for (let index = 0; index < keys.length; index++) {
                result[keys[index]] = array[index];
            }

        }));
}

Пожалуйста, имейте в виду, в данный момент у меня не было ни angular, ни rxjs, поэтому я не мог проверить, действительно ли работает эта функция. Но идея такова: 1. Получить ключи от карты ввода. 2. Используйте ключи, чтобы получить массив наблюдаемых и передать его в fork fork. 3. Добавьте функцию отображения, которая преобразует полученный массив обратно в объект.

0 голосов
/ 12 сентября 2018

Легче всего можно добавить немое Observable.of(null) со значением null, если условие не выполняется, чтобы сохранить тот же порядок ответов:

if (this.task.associatedChatThreadId) {
    observables.push(this.messageHubService....);
} else {
    observables.push(Observable.of(null))
}

Затем в подписке вы можете проверить, если chatThread === null, потому что он всегда будет присутствовать в одной и той же позиции.

В качестве альтернативы, вы могли бы обернуть каждое Наблюдаемое в observables некоторым дополнительным объектом, который сделал бы его уникально идентифицируемым в подписчике, но это было бы излишне сложно, поэтому я лично придерживался бы первого варианта.

...