Angular 在执行其他代码之前,确保for循环中的可观察对象都已完成

Angular 在执行其他代码之前,确保for循环中的可观察对象都已完成,angular,rxjs,Angular,Rxjs,我有一段代码如下所示: getPersons().subscribe( persons => { for (const person of persons) { getAddress(person.id).subscribe( address => { person.address = address; } )

我有一段代码如下所示:

getPersons().subscribe(
    persons => {
        for (const person of persons) {
            getAddress(person.id).subscribe(
                address => {
                    person.address = address;
                }
            );
        }
        doSomethingWithAddresses();
     }
);

问题是doSomethingWithAddresses是在所有getAddress可观察对象完成之前执行的。在执行后续代码之前,如何确保它们都已完成?

在返回所有观察值之前,应该使用RxJS等待for..of循环完成

以下是您应该对代码所做的更改:

getPersons().subscribe(
  persons => {
    const observablesList = [];
    for (const person of persons) {
      const getAddressObservable = getAddress(person.id);
      observablesList.push(getAddressObservable)
    }
    forkJoin(observablesList).subscribe(response => {
      // console.log(response) to check that there is a list of returned observables
      const result = persons.map((person, index) => {
        person['address'] = response[index]['address'];
        return person;
      })
      doSomethingWithAddresses();
    })
  }
);

或者,您可以尝试此操作以防止链接
subscribe()

试试这个方法

methodOne() {
getPersons().subscribe(
    persons => {
        for (const person of persons) {
            getAddress(person.id).subscribe(
                address => {
                    person.address = address;
                }
            );
        }
     }
);
}

async methodTwo() {
await methodOne();
doSomethingWithAddresses();
}

谢谢,这看起来是正确的方法,但在调用doSomethingWithAddresses()之前,我仍然需要将每个地址分配给每个人。用forkJoin可以吗?@Spacejockey实际上是的。当您订阅forkJoin中的Observable时,您会发现它返回了Observable返回值的列表。在伪代码中,您将得到如下内容
[addressObj1、addressObj2、addressObj3等]
。从这里,您可能可以使用Array.map()映射数组中的每个元素,以将地址分配给每个人!让我试着把它添加到我的答案中,以便更清楚地说明它。让我知道如果它有效,我将添加另一个替代解决方案,使它更干净,因为我意识到我在这里嵌套订阅。@wentjun哦,你搞错了,伙计。其实我想学。我在某个地方看到一些人使用mergemap来实现这种场景。但在这里,您创建了一个可观察的列表。我试图理解这个解决方案,并问了这个问题question@SadidKhan很抱歉,我不是故意说得太严厉的。TBH,我认为有几种方法可以解决它,但我的想法是“一块一块”地处理它,并将关注点分开。我认为,如果我们在继续下一组操作之前,等待for..of循环中的可观测值完成,这可能没问题。因此,我决定将它们组合在一起,并在for..of循环完全执行后返回可观测值。。!这是一种“万无一失”的方法,可以确保只有在for循环完成后才会执行
doSomethingWithAddresses()
。因为
methodOne()
没有跟踪其子订阅或返回任何内容,所以
doSomethingWithAddresses()
是否会在不等待它们完成的情况下运行?
let loadedPerson;
getPersons().pipe(
  mergeMap(persons => {
  return of(persons);
}),
mergeMap(person => {
  loadedPerson = person;
  return getAddresses(person.id);
}),
map((address) => {
  loadedPerson.address = address;
}),
tap(()=>{
  doSomethingWithAddresses();
})
).subscribe();
methodOne() {
getPersons().subscribe(
    persons => {
        for (const person of persons) {
            getAddress(person.id).subscribe(
                address => {
                    person.address = address;
                }
            );
        }
     }
);
}

async methodTwo() {
await methodOne();
doSomethingWithAddresses();
}