使用 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))) 解决了。谢谢大家的努力。