angular - 等待所有可观察对象完成(按顺序 + 父子关系)
问题描述
我对 Angular 和 Observables 有疑问,我在这个 Stackblizt 中复制了它:https ://stackblitz.com/edit/angular-ivy-dl1y3y
放一些上下文:
- 我需要调用第一个网络服务。
- 使用第一次调用的数据,我需要调用第二个 Web 服务。
- 使用第二次调用的数据,我需要调用第三组网络服务(“父母与孩子”关系)
- 所有这些信息都将显示在一个表格中(使用Angular Datatables),我不想显示带有部分数据的表格(否则只要所有剩余的可观察数据都完成,剩余的数据就会弹出。我也可能面临一些其他问题,例如用户在部分数据尚不可用时单击按钮...)。所以:我希望所有的 observables 都完成,然后我将完整的对象传递给数据表,一切都会立即显示出来!
- 我想用 Observables 来做,而不是 Promises
好的,让我一步一步地告诉你。
步骤1
第一步是调用第一个 URL ( assets/step-1-getAccountReference.json
) 来检索帐户参考 ID:
{
"accountIdRef": "/assets/step-2.getAccount.json"
}
第2步
有了这个accountIdRef
,我可以调用另一个 URL ( "/assets/step-2.getAccount.json"
) 来检索帐户信息:
{
"accountId": "123",
"details": [
{
"nameRef": "/assets/step-3-pet-1-name.json",
"genderRef": "/assets/step-3-pet-1-gender.json"
},
{
"nameRef": "/assets/step-3-pet-2-name.json",
"genderRef": "/assets/step-3-pet-2-gender.json"
}
]
}
第 3 步
最后一步是for each
通过调用其他一些 url (nameRef
和genderRef
) 来检索所有宠物的详细信息。
如果您打开控制台,您应该会看到,如果我直接订阅并登录帐户,则会显示此信息(步骤 1和步骤 2中的 Observables已完成):
{
"accountId": "123",
"details": [
{
"nameRef": "/assets/step-3-pet-1-name.json",
"genderRef": "/assets/step-3-pet-1-gender.json"
},
{
"nameRef": "/assets/step-3-pet-2-name.json",
"genderRef": "/assets/step-3-pet-2-gender.json"
}
]
}
如果我在 3 秒后再次登录该帐户,则会显示此信息(步骤 3中的所有 observables都已完成):
{
"accountId": "123",
"details": [
{
"nameRef": "/assets/step-3-pet-1-name.json",
"genderRef": "/assets/step-3-pet-1-gender.json",
"name": "Santa's Little Helper",
"gender": "Male"
},
{
"nameRef": "/assets/step-3-pet-2-name.json",
"genderRef": "/assets/step-3-pet-2-gender.json",
"name": "Snowball II",
"gender": "Female"
}
]
}
我想等待所有 observables 完成(包括第 3 步),但当然是动态的,而不是使用固定的超时。
这是我现在所拥有的:
export class HttpService {
constructor(private http: HttpClient) {}
getAccount(): Observable<Account> {
return this.http.get("assets/step-1-getAccountReference.json").pipe( // Step 1
mergeMap((accountReference: AccountReference) => {
return this.http.get("" + accountReference.accountIdRef); // Step 2
}),
delay(500),
map((account: Account) => {
account.details.forEach((details: AccountDetails) => { // Step 3
let name$ = this.http.get("" + details.nameRef);
let gender$ = this.http.get("" + details.genderRef);
forkJoin([name$, gender$]).subscribe(results => {
details.name = results[0]["name"];
details.gender = results[1]["gender"];
});
});
return account;
})
);
}
}
那么,我怎样才能调整这段代码,使第 3 步是同步的?我应该使用哪个运算符来替换它forEach
?
谢谢您的帮助 !
解决方案
您可以做的是映射您的详细信息并构建一个可观察的数组来填充缺失的属性。
然后将该数组传递给 forkJoin,它将丢失的数据提取到您的详细信息中。最后,您更新您的帐户详细信息并返回帐户。
export class HttpService {
constructor(private http: HttpClient) {}
getAccount(): Observable<Account> {
return this.http.get("assets/step-1-getAccountReference.json").pipe( // Step 1
mergeMap((accountReference: AccountReference) => {
return this.http.get("" + accountReference.accountIdRef); // Step 2
}),
delay(500), // why this delay ?
mergeMap((account: Account) => {
const populatedDetailsObservableArray = account.details.map((details: AccountDetails) => {
return forkJoin([name$, gender$]).pipe(
map(results => {
details.name = results[0]["name"];
details.gender = results[1]["gender"];
return details;
})
);
});
return forkJoin(populatedDetailsObservableArray).pipe(
map((newDetails: AccountDetails[]) => {
account.details = newDetails;
return account;
})
);
})
);
}
}
推荐阅读
- python - 如何使用 Python 将正弦波转换为方波(0 或 1)?
- r - 在基础 R 中使用派生轴标记散点图点
- kubernetes - HaProxy - 如何配置绑定到端口 X 的前端,将端口 Y 上的流量传递到默认后端
- python - 如何将所有表存储在数据框中的 sql 数据库中?
- python - ValueError: 层序 7 的输入 0 与层不兼容:输入形状的预期轴 -1 具有值 5,但接收到的形状(无,21)
- python - 无法从 github 安装 python 模块
- javascript - 使用 JavaScript 函数在 Django 中操作变量的输出
- python-3.x - 为什么同一个对象有不同的id?
- javascript - 将数据从 JSON 传递到 HTML
- powershell - Powershell:无法从主机读取和写入 Hyperv-V VM 上的变量