Estoy tratando de llamar a dos observables, con la respuesta del segundo manipulo el primero y luego devuelvo un nuevo observable.

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) es otra función que devuelve un observable.

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

Todo lo que quiero hacer es obtener el objeto de usuario de la primera llamada http, realizar otra solicitud utilizando el id del usuario en la segunda llamada y luego, después de recuperar la respuesta del segundo observable, actualizo una propiedad de primera respuesta y devuelve la primera respuesta actualizada. ¿Cómo logro esto? ¿Qué función de rxjs debería mirar?

2
Anjil Dhamala 13 sep. 2018 a las 01:52

3 respuestas

La mejor respuesta

Estuviste cerca en tu ejemplo.

Desea utilizar switchMap que cancela la suscripción al observable entrante y se suscribe al siguiente observable.

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();

La respuesta se pasará a isFirstTimeuser() y se aplicará lo siguiente .map() a los observables devueltos por esa función.

Se llama switchMap porque el observable devuelto por this.http.get() es sin suscripción y se usa el siguiente observable. Esto no será un problema con this.http.get(), pero tenga en cuenta que switchMap solo funciona para el primer valor emitido.

1
Reactgular 12 sep. 2018 a las 23:25

Use mergeMap

return this.http.get(requestUrl)
            .mergeMap((response: User) => {
                const currentUser = response;
                currentUser.firstTimeLogin = this.isFirstTimeUser(response.id) === 'true' 
                return Observable.of(currentUser);
            })
0
Fartab 12 sep. 2018 a las 23:32

La solución que estás buscando es algo así:

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;
        });
}

Entonces solo necesita suscribirse a getUser() y debería estar bien. Todavía no es el mejor código según el paradigma funcional de funciones puras de rxjs. Supongo que usar concatMap con la función de proyección nos acercaría al ideal, pero funcionará.

La razón por la que no es ideal es porque hay un efecto secundario requerido en el primer bloque .do(), actualizamos el valor sessionManager, una variable fuera de la función (un gran no no en el mundo funcional) y luego accedemos de nuevo en la función .map(). concatMap con la función de proyección como un segundo argumento nos ayudaría a resolver esto.

2
codeepic 12 sep. 2018 a las 23:56