RXJS: вернуть манипулируемое значение внешнего наблюдаемого - PullRequest
0 голосов
/ 13 сентября 2018

Я пытаюсь вызвать две наблюдаемые, с ответом секунды я манипулирую первой, а затем возвращаю новую наблюдаемую.

return this.http.get(requestUrl)
            .map((response: User) => {
                sessionManager.currentUser = response;
                return this.isFirstTimeUser(response.id);
            })
            .do((response: any) => {
                console.log(response);
                sessionManager.currentUser.firstTimeLogin = response === 'true';
                return Observable.create(sessionManager.currentUser);
            })
            .toPromise();

isFirstTimeUser (response.id) - это еще одна функция, которая возвращает наблюдаемое.

private isFirstTimeUser(userId: number): Observable<any> {
        const requestUrl = 'someUrl';
        return this.http.get(requestUrl, {responseType: 'text'});
    }

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

Ответы [ 3 ]

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

Вы были близки в вашем примере.

Вы хотите использовать switchMap, который отменяет подписку на входящую наблюдаемую, а подписывает на следующую наблюдаемую.

return this.http.get(requestUrl)
        .switchMap((response: User) => {
            sessionManager.currentUser = response;
            return this.isFirstTimeUser(response.id);
        })
        .map((response: any) => {
            console.log(response);
            sessionManager.currentUser.firstTimeLogin = response === 'true';
            return sessionManager.currentUser;
        })
        .toPromise();

Ответ будет передан на isFirstTimeuser(), а следующий .map() будет применен к наблюдаемому объекту, возвращенному этой функцией.

Он называется switchMap, потому что наблюдаемое, возвращаемое this.http.get(), равно отписано и используется следующая наблюдаемая. Это не будет проблемой для this.http.get(), но имейте в виду, что switchMap работает только для значения first .

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

Решение, которое вы ищете, выглядит примерно так:

getUser(): Observable<any>{
    return this.http.get(reqUrl)
        .do((res: User) => {
            sessionManager.currentUser = res;
        })
        .switchMap((res: User) => {
            return this.isFirstTimeUser(res.id);
        })
        .do((res: any) => {
            console.log(response);
        }
        .map((res: any) => {
            sessionManager.currentUser.firstTimeLogin = res === 'true';
            return sessionManager.currentUser;
        });
}

Тогда вам просто нужно подписаться на getUser(), и вы должны быть в порядке.Это все еще не лучший код в соответствии с функциональной парадигмой rxjs чистых функций.Я предполагаю, что использование concatMap с функцией проекции приблизит нас к идеалу, но это сработает.

Причина, по которой он не идеален, заключается в том, что в первом блоке .do() есть обязательный побочный эффект, мы обновляем значение sessionManager - переменную вне функции (большая нет в функциональном мире), а затеммы снова получаем доступ к нему в функции .map().concatMap с функцией проекции в качестве второго аргумента поможет нам обойти это.

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

Использовать mergeMap

return this.http.get(requestUrl)
            .mergeMap((response: User) => {
                const currentUser = response;
                currentUser.firstTimeLogin = this.isFirstTimeUser(response.id) === 'true' 
                return Observable.of(currentUser);
            })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...