簡體   English   中英

Angular 7嵌套可觀察對象

[英]Angular 7 nested observables

我有兩個收藏:人和寵物。 每個寵物都有personId。 我的目標是吸引所有人,並讓每個人在單個json中添加他/她的寵物。 到目前為止,我所做的是:

this.personService.getPersions().subscribe(persons => {
  const personsWithPets = persons.flatMap(person => this.petService.getPetsByPersonId(person._id)
    .subscribe(petsData => {
      person.pets = petsData;
      return person;
    }, (err) => {
     console.log(err);
    }));
  this.persons = personsWithPets; // This is fired before previous subscribe
}, (err) => {
  console.log(err);
});

我做錯了什么? 為什么this.persons = personsWithPets; 在訂閱完成之前被解雇?

我為你樹立了榜樣

 const { of } = rxjs; const { map, switchMap, toArray, mergeMap } = rxjs.operators; function getPeople() { return of([{ id: 1, name: 'Amanda' }, { id: 2, name: 'Nancy' }]); } function getPetsByPersonId(id) { switch(id) { case 1: return of(['Doggie']); case 2: return of(['Kitten']); } } const getPets = (person) => { return getPetsByPersonId(person.id).pipe( map(pets => ({ ...person, pets })) ) } getPeople().pipe( switchMap(people => people), mergeMap(getPets), toArray() ) .subscribe(peopleWithPets => console.log(peopleWithPets)); 
 <script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script> 

在內部使用訂閱進行訂閱被認為是不好的做法,並且可能會導致您所描述的問題。 我建議結合使用mergeMap和forkJoin運算符:

 this.personService.getPersions().pipe(mergeMap(persons => { const requests = persons.map(person => this.petService.getPetsByPersonId(person._id)); return forkJoin(of(persons), ...requests); }), map(values => { const persons = values[0]; const pets = values.slice(1); // here you need to assign correct pet to correct person }) ).subscribe(personsWithPets => { console.log(personsWithPets); }, err => { console.log(err); }); 

更新了添加的注釋

另一個: stackblitz

this.service.getPersons().pipe(switchMap((per:any[])=>{
       //create an array of observables
       const obs=per.map(per=>this.service.getPet(per.id));
       //call all of them in forkjoin
       return forkJoin(obs).pipe(map(pets=>
         //pets is an array, in pets[0] is the response of getPet(1), 
         //in pets[1] is the response of getPet(2)
         pets.map((pet,i)=>{
           return {
             ...per[i], //all the properties of the person
             pets:pet   //+ in pets an array with the pets of the person
             }
         })
       ))
     })).subscribe(res=>this.res=res)

可觀察的對象本質上是異步的。 訂閱調用將在另一個線程中運行,而該方法中的其余指令將繼續在主線程中運行。 您需要做的是等到異步操作完成后再運行下一個操作。 您可以通過將這些注解放置在訂閱中來做到這一點,或者更好的方法是使用(err)參數之后的onCompleted參數,如下所示

this.personService.getPersons().subscribe(persons => {
  const personsWithPets = persons.flatMap(person => 
        this.petService.getPetsByPersonId(person._id)
            .subscribe(petsData => {
                 person.pets = petsData;
                 return person;
             }, 
             (err) => {
                 console.log(err);
             },
             () => {
                 this.persons = personsWithPets;
             }))
        });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM