Home > database >  Switchmap operator not iterating through the values returned from observable
Switchmap operator not iterating through the values returned from observable

Time:10-11

I have 2 firebase list Raw Materials & Stock. The stock list contains objects with a raw material key. i use that key to fetch the raw material. I'm getting all the stock list , then when i iterate through each object in the list to join the raw material, the problem is that the observable returns only the first object. meaning, it doesn't iterate through all the list. here's my code

  rawMaterialsStocksRef: AngularFireList<any>;
  rawMaterialStockRef: AngularFireObject<any>;


  private dbPathStock = '/raw_material_stock';

  constructor(
    private db: AngularFireDatabase,
    private rawMaterialService: RawMaterialsManagementService
  ) {
    this.rawMaterialsStocksRef = db.list(this.dbPathStock);
  }

getRawMaterialStockList() {
  
   const rawData = this.rawMaterialsStocksRef.valueChanges().pipe(
      map(rawMaterialsStocks =>
        rawMaterialsStocks.map(stock => ({
         ...stock
        }))
      ),
      switchMap(stockArr => from(stockArr)), 
      // gives the following 
      // { "factoryKey": "34""quantity": "34", "rawMaterialKey": "-NDNPe47CDTbjmwGgW_3"}
      // { "factoryKey": "20", "quantity": "20", "rawMaterialKey": "-NDIjiVqKP-lLwJGwmic"}
      switchMap(stock =>
        // this service i use to fetch each raw material based on its key
        this.rawMaterialService.getRawMaterial(stock.rawMaterialKey).valueChanges()
          .pipe(
            map(rawMaterial => {
              return { ...stock, ...rawMaterial }
            })
          )
      ),
    );
   
   rawData.subscribe()
}

here is the result i'm getting

{
    "factoryKey": "20",
    "quantity": "20",
    "rawMaterialKey": "-NDIjiVqKP-lLwJGwmic",
    "code": "KLL2311",
    "name": "Material 03"
}

as you can see i only got one successful join, despite the array containing multiple objects !

PLEASE HELP ME OUT I SPENT THE 3 DAYS TRYING EVERYTHING, DIDNT WORK OUT !

enter image description here

CodePudding user response:

switchMap

the switch in switchMap is meant to denote the extra behaviour of the operator. Switch means "drop the previous observable if it's active, switch to this one instead."

concatMap means "If there's still an active obserable, put this in the queue to be run as soon as the previous observables complete"

mergeMap means "I don't care if or how many previous observables are running at the moment. Subscribe to them all and emit whatever any source observable emits"


Change your switchmap to one of the other two

mergeMap(stock => this.rawMaterial..........
  ........

An Aside

I suggest you pick one programming style. Your code has both

map(stock => ({
  ...stock
}))

map(rawMaterial => {
  return { ...stock, ...rawMaterial }
})

Option one:

map(stock => ({
  ...stock
}))

map(rawMaterial => ({ 
  ...stock, ...rawMaterial 
}))

option 2:

map(stock => {
  return { ...stock }
})

map(rawMaterial => {
  return { ...stock, ...rawMaterial }
})

Mixing them so both are in the same small segment of code makes it so much harder to skim through code coherently.

Update # 1

Using forkJoin to return an array of results in parallel.

mergeMap(stockArr => forkJoin(stockArr.map(stock =>
  this.rawMaterialService
    .getRawMaterial(stock.rawMaterialKey)
    .valueChanges()
    .pipe(
      map(rawMaterial => ({ ...stock, ...rawMaterial }))
    )
)))
  • Related