Цепочка Angular 6 RxJS с несколькими зависимыми подписками

Я надеюсь, что кто-то может дать небольшой совет о том, как сделать следующее:

У меня есть требование связать несколько http-запросов, каждый из которых зависит от результата предыдущего.

i.e

Шаг 1: Войдите в систему

Шаг 2: HTTP-запрос с проверкой подлинности

Шаг 3: Аутентифицированный HTTP-запрос со значением ответа из шага 2.

Шаг 4: Аутентифицированный HTTP-запрос со значением ответа из шага 3

Пока у меня есть следующий код (который работает):

this.authSandbox.login(this.loginForm).subscribe(() => {

    this.customerEnquirySandbox.createCustomer(newCustomer)
    .filter(response => !!response) // continue when response not null
    .subscribe((response) => {

        let response1Details = {
            "id": response.data.id,
        };

        this.customerEnquirySandbox.createMeasure(response1Details )
        .filter(response => !!response)
        .subscribe((response) => {

            let response2Details =  {
                "id": response.data.id,
            };

            this.customerEnquirySandbox.saveAnswers(response2Details )
            .filter(response => !!response)
            .subscribe((response) => {

                if (response.data.success) { 
                    alert('Form completed and answers saved successfully');
                } else {
                    alert('Error submitting answers');
                }

                this.authSandbox.customerEnquirylogout();
            });

        });

    });

});

Вышеприведенное работает, но не кажется наиболее подходящим способом. У меня есть предложения с использованием switchMap, но я не уверен, что это правильный подход. Если кто-нибудь может предложить какие-либо рекомендации о том, как сделать вышеизложенное более правильно, то это будет высоко оценено.

заранее спасибо


person ledragon    schedule 17.07.2019    source источник
comment
Используйте оператор switchMap   -  person JB Nizet    schedule 17.07.2019
comment
Я думаю, вы ищете Observable.combineLatest   -  person Ben Hulan    schedule 17.07.2019
comment
@JBNizet Спасибо за ответ ... да, я понял, что это правильный подход, но мне не удалось реорганизовать приведенный выше код, чтобы он работал.   -  person ledragon    schedule 26.07.2019


Ответы (1)


Как предложил JB, switchMap — это то, что нужно, если каждый последующий вызов зависит от предыдущего, а если их можно выполнять параллельно, то zip — отличный вариант. Вот ваш код, переработанный для использования switchMap

this.authSandbox.login()
    .pipe(
        filter(response => !!response),
        switchMap(response => {
            return this.customerEnquirySandbox.createCustomer(newCustomer);
        }),
        filter(response => !!response),
        switchMap(response => {
            return this.customerEnquirySandbox.createMeasure(response.data);
        }),
        filter(response => !!response),
        switchMap(response => {
            return this.customerEnquirySandbox.saveAnswers(response.data);
        }),
        filter(response => !!response),
        switchMap((response): Observable<never> => {
            if (response.data.success) {
                alert('Form completed and answers saved successfully');
            } else {
                alert('Error submitting answers');
            }
            this.authSandbox.customerEnquirylogout();
            return EMPTY; /* EMPTY is a Observable which immediately completes */
        }),
    );

Узнайте о switchMap здесь

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

person Jack W    schedule 18.07.2019
comment
К сожалению, компилятору не нравится синтаксис... все равно спасибо - person ledragon; 26.07.2019
comment
@ledragon, если вы не опубликуете код, который вы пробовали, и ошибку, которую вы получили, мы не сможем вам помочь. Код, который вы разместили в своем вопросе, показывает, что вы используете устаревшую версию RxJS. Сейчас у Angular версия 8, а начиная с версии 6 он использует RxJS 6. Вы используете более старую версию. Время обновить. - person JB Nizet; 27.07.2019