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 !
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 }))
)
)))