使用 RxJS 和 combineLatest 的函数有时有效,有时无效
Function with RxJS and combineLatest sometimes works and sometimes doesn't
如果多次调用此函数且每次观察对象 obs1 和 obs2 的值都相同,则返回的数组并不总是相同的。
getProductosUnicos(obs1: Observable<any>, obs2: Observable<any>): Observable<any> {
return combineLatest([obs1, obs2])
.pipe(
map(([prod1, prod2]) => {
return prod1.find((prod: any) => prod1.NombreProducto === prod2)
}),
toArray(),
tap( a => console.log(a.length))
)
}
我要获取的是来自 obs1 的对象,其 NombreProducto 与来自 obs2 的字符串相匹配。
根据 Liam 的要求,我添加了更多代码以便更好地理解:
// component.ts
getProductos() {
this._gasolinerasService.getProductosUnicos(
this._gasolinerasService.getProductos(),
this._gasolinerasService.getProductosMunicipio(this.idMunicipio)
).subscribe( (data: any) => {
this.productos = data
if(!this.default) {
if (this.idProducto == '') {
this.idProducto = data[0].IDProducto;
this.producto = data[0].NombreProducto;
}
}
this.getGasolineras();
})
}
// service.ts
baseUrlGasolinerasMunicipio = "https://sedeaplicaciones.minetur.gob.es/ServiciosRESTCarburantes/PreciosCarburantes/EstacionesTerrestres/FiltroMunicipio/";
baseUrlProductos = "https://sedeaplicaciones.minetur.gob.es/ServiciosRESTCarburantes/PreciosCarburantes/Listados/ProductosPetroliferos/";
getProductos(): Observable<any> {
return this._httpClient.get<Producto[]>(this.baseUrlProductos)
}
getProductosMunicipio(idMunicipio: string): Observable<any> {
return this._httpClient.get<Gasolinera[]>(this.baseUrlGasolinerasMunicipio + idMunicipio).pipe(
map((data: any) => data.ListaEESSPrecio.map((data: any) =>
({
"Biodiésel": data["Precio Biodiesel"],
"Bioetanol": data["Precio Bioetanol"],
"Gas natural comprimido": data["Precio Gas Natural Comprimido"],
"Gas natural licuado": data["Precio Gas Natural Licuado"],
"Gases licuados del petróleo": data["Precio Gases licuados del petróleo"],
"Gasóleo A habitual": data["Precio Gasoleo A"],
"Gasóleo B": data["Precio Gasoleo B"],
//"Gasóleo C": data["Precio Gasoleo C"],
"Gasóleo Premium": data["Precio Gasoleo Premium"],
"Gasolina 95 E10": data["Precio Gasolina 95 E10"],
"Gasolina 95 E5": data["Precio Gasolina 95 E5"],
"Gasolina 95 E5 Premium": data["Precio Gasolina 95 E5 Premium"],
"Gasolina 98 E10": data["Precio Gasolina 98 E10"],
"Gasolina 98 E5": data["Precio Gasolina 98 E5"],
})
)),
concatMap(from),
map(gasolinera => Object.keys(gasolinera).filter(k => gasolinera[k] !== '')),
reduce((acc: string[], item: string[]) => acc.concat(item)),
map(data => data.filter((item: string, index: number) => data.indexOf(item) === index)),
map(data => data.sort((a: any, b: any) => b.localeCompare(a))),
concatMap(from),
);
}
getProductosUnicos(obs1: Observable<any>, obs2: Observable<any>): Observable<any> {
return combineLatest([obs1, obs2])
.pipe(
map(([productos, prodGasolinera]) => {
return productos.find((prod: any) => prod.NombreProducto === prodGasolinera)
}),
toArray(),
tap( a => console.log("sdsf " + a.length))
)
}
尝试像这样更改您的组件代码,看看是否有帮助。基本上,您将 observables 存储在私有变量中,然后将其传递给服务中最新的组合。
export class MyComponent {
...
idMunicipio = "";
private productos$ = this.productoService.getProductos();
private productosMunicipio$ = this.productoService.getProductosMunicipio(this.idMunicipio);
...
// Use the observable variables in the getProductos() call
getProductos() {
this._gasolinerasService.getProductosUnicos(this.productos$, this.productosMunicipio$)
.subscribe( (data: any) => {
this.productos = data
if(!this.default) {
if (this.idProducto == '') {
this.idProducto = data[0].IDProducto;
this.producto = data[0].NombreProducto;
}
}
this.getGasolineras();
});
}
}
我终于解决了。 concatMap(from)
立即发出,因此 combineLatest
并不总是按预期工作。我用 concatMap(a => from(a).pipe(delay(1)))
解决了。谢谢大家的努力。
如果多次调用此函数且每次观察对象 obs1 和 obs2 的值都相同,则返回的数组并不总是相同的。
getProductosUnicos(obs1: Observable<any>, obs2: Observable<any>): Observable<any> {
return combineLatest([obs1, obs2])
.pipe(
map(([prod1, prod2]) => {
return prod1.find((prod: any) => prod1.NombreProducto === prod2)
}),
toArray(),
tap( a => console.log(a.length))
)
}
我要获取的是来自 obs1 的对象,其 NombreProducto 与来自 obs2 的字符串相匹配。
根据 Liam 的要求,我添加了更多代码以便更好地理解:
// component.ts
getProductos() {
this._gasolinerasService.getProductosUnicos(
this._gasolinerasService.getProductos(),
this._gasolinerasService.getProductosMunicipio(this.idMunicipio)
).subscribe( (data: any) => {
this.productos = data
if(!this.default) {
if (this.idProducto == '') {
this.idProducto = data[0].IDProducto;
this.producto = data[0].NombreProducto;
}
}
this.getGasolineras();
})
}
// service.ts
baseUrlGasolinerasMunicipio = "https://sedeaplicaciones.minetur.gob.es/ServiciosRESTCarburantes/PreciosCarburantes/EstacionesTerrestres/FiltroMunicipio/";
baseUrlProductos = "https://sedeaplicaciones.minetur.gob.es/ServiciosRESTCarburantes/PreciosCarburantes/Listados/ProductosPetroliferos/";
getProductos(): Observable<any> {
return this._httpClient.get<Producto[]>(this.baseUrlProductos)
}
getProductosMunicipio(idMunicipio: string): Observable<any> {
return this._httpClient.get<Gasolinera[]>(this.baseUrlGasolinerasMunicipio + idMunicipio).pipe(
map((data: any) => data.ListaEESSPrecio.map((data: any) =>
({
"Biodiésel": data["Precio Biodiesel"],
"Bioetanol": data["Precio Bioetanol"],
"Gas natural comprimido": data["Precio Gas Natural Comprimido"],
"Gas natural licuado": data["Precio Gas Natural Licuado"],
"Gases licuados del petróleo": data["Precio Gases licuados del petróleo"],
"Gasóleo A habitual": data["Precio Gasoleo A"],
"Gasóleo B": data["Precio Gasoleo B"],
//"Gasóleo C": data["Precio Gasoleo C"],
"Gasóleo Premium": data["Precio Gasoleo Premium"],
"Gasolina 95 E10": data["Precio Gasolina 95 E10"],
"Gasolina 95 E5": data["Precio Gasolina 95 E5"],
"Gasolina 95 E5 Premium": data["Precio Gasolina 95 E5 Premium"],
"Gasolina 98 E10": data["Precio Gasolina 98 E10"],
"Gasolina 98 E5": data["Precio Gasolina 98 E5"],
})
)),
concatMap(from),
map(gasolinera => Object.keys(gasolinera).filter(k => gasolinera[k] !== '')),
reduce((acc: string[], item: string[]) => acc.concat(item)),
map(data => data.filter((item: string, index: number) => data.indexOf(item) === index)),
map(data => data.sort((a: any, b: any) => b.localeCompare(a))),
concatMap(from),
);
}
getProductosUnicos(obs1: Observable<any>, obs2: Observable<any>): Observable<any> {
return combineLatest([obs1, obs2])
.pipe(
map(([productos, prodGasolinera]) => {
return productos.find((prod: any) => prod.NombreProducto === prodGasolinera)
}),
toArray(),
tap( a => console.log("sdsf " + a.length))
)
}
尝试像这样更改您的组件代码,看看是否有帮助。基本上,您将 observables 存储在私有变量中,然后将其传递给服务中最新的组合。
export class MyComponent {
...
idMunicipio = "";
private productos$ = this.productoService.getProductos();
private productosMunicipio$ = this.productoService.getProductosMunicipio(this.idMunicipio);
...
// Use the observable variables in the getProductos() call
getProductos() {
this._gasolinerasService.getProductosUnicos(this.productos$, this.productosMunicipio$)
.subscribe( (data: any) => {
this.productos = data
if(!this.default) {
if (this.idProducto == '') {
this.idProducto = data[0].IDProducto;
this.producto = data[0].NombreProducto;
}
}
this.getGasolineras();
});
}
}
我终于解决了。 concatMap(from)
立即发出,因此 combineLatest
并不总是按预期工作。我用 concatMap(a => from(a).pipe(delay(1)))
解决了。谢谢大家的努力。