Búsqueda de sitios web

javascript - RxJS Observable.concat: ¿Cómo saber de dónde provino el siguiente resultado?


Mi aplicación (Angular 2 con RxJS 5 escrita en TypeScript) requiere que haga 2 llamadas a un servicio web en un orden predefinido. Inspirado por esta página, decidí probar el operador concat de los observables de RxJS. La complicación es que el callback onNext que recibe los valores necesita enviarlos a diferentes manejadores dependiendo de dónde provienen.

Mi código se puede simplificar a:

suscription1 = Observable.return({name:'John', age:7});
subscription2 = Observable.return({name:'Mary', color:'blue'}); 
Observable.concat(subscription1, subscription2).subscribe(
    data=>{ /* need to know which subscripion 
             i'm dealing with to direct to the right handler*/}
);

¿Cuál es la manera más elegante de determinar de dónde provienen mis datos en cada emisión observable? He pensado en un par de maneras, pero todas parecen torpes:

  1. Mantén un contador en el alcance, quizás como una propiedad de la clase. Revísalo y incrementalo cada vez que recibas un resultado. Dado que cada observable emite solo una vez, el contador tendrá su valor inicial cuando la primera suscripción emita y tendrá inicial+1 cuando la segunda emita. El problema es que esto no funcionará cuando no sepa cuántas veces cada observable emitirá antes de completarse.

  2. Inspecciona cada resultado e identifica su fuente por la forma del resultado. Por ejemplo, en mi ejemplo, solo el resultado del primer observable tiene una propiedad age. Obviamente, esto se vuelve poco práctico cuando los resultados tienen la misma forma.

  3. Deshazte del operador concat por completo; suscríbete a subscription2 en el manejador onComplete de subscription1. Esto funcionaría, pero no escala bien; si tengo 4 o 5 suscripciones para concatenar, se vuelve un infierno anidado.

Solución 3 con solo 2 suscripciones...

suscription1 = Observable.return({name:'John', age:7});
subscription2 = Observable.return({name:'Mary', age:8}); 
subscription1.subscribe(
    data=> this.handlerOne(data),
    error=>{},
    ()=> {
        subscription2.subscribe(
            data=>this.handlerTwo(data),
            error=>{},
            ()=>console.log('All subscriptions completed!')
        )
    }
);

Entonces mi pregunta: Al usar Observable.concat para suscribirse a varios observables en secuencia, ¿cómo puede mi manejador onNext determinar de dónde provienen los datos? Alternativamente, ¿hay otro operador que debería estar usando para este propósito? No puedo usar el operador forkJoin porque el orden en que se completan las suscripciones es importante.

Respuesta #1

Podrías mapear las suscripciones para saber de dónde vienen.

suscription1 = Observable.return({name:'John', age:7})
         .map(person => { person.source = 1; return person };
subscription2 = Observable.return({name:'Mary', age:8})
         .map(person => { person.source = 2; return person };

Entonces puedes determinar fácilmente de dónde proviene:

Observable.concat(subscription1, subscription2).subscribe(
    data=> { if (data.source == 1) /* do whatever */ }
);

Artículos relacionados