reactive-programming - que - rxjs observable angular
En RxJava, ¿cómo pasar una variable cuando se encadenan los observables? (6)
Estoy encadenando operaciones asíncronas usando RxJava, y me gustaría pasar alguna variable en sentido descendente:
Observable
.from(modifications)
.flatmap( (data1) -> { return op1(data1); })
...
.flatmap( (data2) -> {
// How to access data1 here ?
return op2(data2);
})
Parece un patrón común pero no pude encontrar información al respecto.
El consejo que recibí del foro de Couchbase es usar observables anidados:
Observable
.from(modifications)
.flatmap( (data1) -> {
return op1(data1)
...
.flatmap( (data2) -> {
// I can access data1 here
return op2(data2);
})
});
EDITAR: marcaré esto como la respuesta aceptada ya que parece ser la más recomendada. Si su procesamiento es demasiado complejo para anidar todo, también puede verificar la solución con llamadas de función.
La solución en este hilo funciona, pero para las cadenas complejas hace que el código sea difícil de leer, tuve que pasar varios valores y lo que hice fue crear una clase privada con todos los parámetros, creo que el código es más legible de esta manera.
private class CommonData{
private string data1;
private string data2;
*getters and setters*
}
...
final CommonData data = new CommonData();
Observable
.from(modifications)
.flatmap( (data1) -> {
data.setData1(data1);
return op1(data1);
})
...
.flatmap( (data2) -> {
data2 = data.getData1() + "data 2... ";
data.setData2(data2);
return op2(data2);
})
Espero eso ayude
Otra posibilidad es mapear el resultado de op1
a una org.apache.commons.lang3.tuple.Pair
que contiene la variable y pasar eso:
Observable
.from(modifications)
.flatmap( (data1) -> {
return op1(data1).map( obj -> { return Pair.of(data1,obj); });
})
...
.flatmap( (dataPair) -> {
// data1 is dataPair.getLeft()
return op2(dataPair.getRight());
})
Funciona, pero se siente un poco incómodo tener variables ocultas dentro de un Par / Triple / ... y se vuelve muy detallado si usa la notación de Java 6.
Me pregunto si hay una solución mejor, tal vez algún operador de RxJava pueda ayudar?
Puedes usar la variable "global" para lograr esto:
Object[] data1Wrapper = new Object[]{null};
Object[] data2Wrapper = new Object[]{null};
Observable
.from(modifications)
.flatmap(data1 -> {
data1Wrapper[0] = data1;
return op1(data1)
})
...
.flatmap(data2 -> {
// I can access data1 here use data1Wrapper[0]
Object data1 = data1Wrapper[0];
data2Wrapper[0] = data2;
return op2(data2);
})
Una posibilidad sería usar una llamada de función:
private static Observable<T> myFunc(final Object data1) {
return op1(data1)
...
.flatmap( (data2) -> {
// I can access data1 here
return op2(data2);
});
}
Observable
.from(modifications)
.flatmap( (data1) -> { return myFunc(data1); })
PERO: corríjame si me equivoco, pero no se siente como la forma de programación reactiva de hacerlo
flatmap puede tomar un segundo arg:
Observable.just("foo")
.flatMap(foo -> Observable.range(1, 5), Pair::of)
.subscribe(pair -> System.out.println("Result: " + pair.getFirst() + " Foo: " + pair.getSecond()));