angular using an observable within an observable

ⅰ亾dé卋堺 提交于 2021-02-04 21:32:35

问题


I am making an expense manager webapp with angular 6. My database is on firebase. I am using the angularfire2 lib to retrieve and update the data.

the database is designed as follows

the function to get a category is

getCategory(uid:String,categorykey:string):Observable<any> 
   {

return this.afdb.object(`users/${uid}/categories/${categorykey}`)
  .snapshotChanges()
  .pipe(map(c=>({key:c.payload.key,...c.payload.val()})));}

the function that returns observable with an array of expenses is

getExpensesWithKeys(uid:String):Observable<any>{
return this.afdb.list(users/${uid}/expenses)
.snapshotChanges()
.pipe(
  map(changes =>
  changes.map(c => 
({key:c.payload.key,...c.payload.val()}))
  )
);
 }

In my component I can get my expenses as

expenses:Expense[];
getExpensesWithKey("userid-123")
.subscribe(expenses=>this.expenses=expenses)

and any category as

category:Category;
getCategory("userid-123",expenses[0].category)
.subscribe(category=>this.category=category);

I want to create an observable that gets the expenses array and returns the category for each expense which i can push into an array of categories. I've been racking my brain to combine the two observables with all kinds of rxjs operaters but to no avail.

Would really appreciate some help.

edit: Just wanted to add a few methods I tried already. One method I tried was

this.getExpensesWithKeys("user-123")
.pipe(mergeMap(expenses=>
expenses.map(expense=>
this.getCategory("user-123",expense.category)))).subscribe(console.log);

but it just emitting an array of Observables. How can i get the category objects and push them into an array?

Another method I tried

this.rtdbService.getExpensesWithKeys("user-123")
.pipe(map(expenses=>
   expenses.map(expense=>expense.category)))
   .pipe(mergeMap(ids=>
this.rtdbService.getCategory("user-123",ids)))
.subscribe(console.log);

This is only emitting the keys of the categories.

I also tried the below provided answer as well which is not emitting anything.

thanks in advance


回答1:


I finally found the solution

  getExpensewithCategories(uid:String):Observable<any>{
    ;
    let expwithCat$=this.getExpenses(uid).pipe(mergeMap(expenses =>{
      return expenses.map(expense => this.getCategory(uid,expense.category)
      .pipe(map(cat=>
        ({expensekey:expense.key,
          amount:expense.amount,
          date:expense.date,
          expcatkey:expense.category,
          categorykey:cat.key,
          color:cat.color,
          name:cat.name})
        )
      ))
   }
    }));

      return expwithCat$.pipe(mergeAll())
}



回答2:


Combine mergeMap to chain observables with forkJoin to make several calls at once :

getBothCategoryAndExpenses(uid) {
  return this.getExpensesWithKeys(uid).pipe(
    mergeMap(expenses => forkJoin(expenses.map(expense => this.getCategory(uid, expense.key)))
    )
  );
}


来源:https://stackoverflow.com/questions/51819588/angular-using-an-observable-within-an-observable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!