gpt4 book ai didi

angular - 订阅 Created Observable 再次调用 Api

转载 作者:太空狗 更新时间:2023-10-29 19:29:59 24 4
gpt4 key购买 nike

我有一个 Api,它返回一个对象数组并将其转换为 ng2-select2 的对象像这样

    getRoles(): Observable<Array<Select2OptionData>> {
return this.authHttp.get(`${this.usersUrl}/GetRoles`)
.map(function (response) {
var result = response.json();

var temp = [];
result.forEach(function (dept) {
var d = {
'id': '0',
'text': dept.name,
'children': []
};

dept.roles.forEach(function (role) {
var r = {
'id': role.id.toString(),
'text': role.name
};
d.children.push(r);
}, this);
temp.push(d);
}, this);
return temp;
})
.catch(this.handleError);
}

返回的是一个包含子项的 Select2OptionData 数组

export interface Select2OptionData {
id: string;
text: string;
children?: Array<Select2OptionData>;
additional?: any;
}

为了加载下拉列表,我必须像这样将可观察对象传递给它

getRoles(): void {
this.roleDepartments = this.userService
.getRoles();
}

<select2 class="form-control" [data]="roleDepartments | async" (valueChanged)="changed($event)" [width]="300"></select2>

这按预期工作,下拉列表在加载时填充了数据。我现在希望能够捕获在更改时选择并受支持的值。问题是我需要遍历“roleDepartments”的值并获取所选值的整个对象。由于该对象是 Observable 对象,因此我无法对其进行迭代。我试过订阅它,将结果分配给一个变量并对其进行迭代。当我尝试这样做时,再次调用填充 Observable 的 Api。我打算以最好的方式做到这一点吗?如果没有,我应该做什么?

最佳答案

首先,再次订阅 observable 的原因是它是所谓的“冷 observable”。这意味着每个新订阅者都将获得一份新的可观察对象副本,并开始为创建该可观察对象所做的任何工作。在 Http 的情况下,它会发出一个新的请求。

因此,我们需要一种方法将其从“冷”可观察对象转变为在我们订阅时不会重新提交请求,而是立即返回最新结果的对象。我们可以通过添加 .publishReplay(1) 运算符,然后添加 .refCount() 运算符来做到这一点,以便第一个订阅者启动请求,最后一个取消订阅者取消订阅相关的可观察对象。

这样,在change()方法中,您可以:

this.roleDepartments.take(1).subscribe(roles => {
let option: Select2OptionData;
roles.forEach(role => {
if (role.id === selectedId) {
option = role;
}
});
});

这将仅获取重播值(原始可观察对象发出的最新值),然后通过 .take(1) 取消订阅。

我相信,这种方法不太容易泄漏,因为没有机会留下您忘记取消订阅的 observable 的悬空订阅。这是因为使用 async 管道是安全的——Angular 负责为您正确订阅和取消订阅,而 change() 方法中的另一个订阅仅在初始订阅之后发生加载数据,然后立即自动取消订阅。

更简单的方法

一个更简单的解决方案(更容易搞砸并导致泄漏)是让您的组件在 ngOnInit() Hook 中订阅一次可观察对象,存储 Angular 色数组以及订阅对象,然后在 ngOnDestroy() Hook 中取消订阅。最后,在模板中,您根本不需要使用 async 管道。

更容易导致泄漏,因为如果您(或 future 的开发人员)忘记取消订阅,您将面临通过阻止清理 Controller 实例而引入内存泄漏的风险。

但是如果您愿意承担这个风险,那么它应该是这样的:

 @Component({
// ...
})
export class MyComponent implements OnInit, OnDestroy {
private rolesSubscription: Subscription;
private roleDepartments: Select2OptionData[];

constructor(private userService: UserService) { }

ngOnInit(): void {
this.rolesSubscription = this.userService.getRoles()
.subscribe(roles => this.roleDepartments = roles);
}

ngOnDestroy(): void {
this.rolesSubscription.unsubscribe();
}

change(selectedId: string) {
// find correct role from this.roles and do something with it
}
}

然后在您的模板中,将其稍微更改为:

<select2 class="form-control" [data]="roleDepartments" 
(valueChanged)="changed($event)" [width]="300">
</select2>

关于angular - 订阅 Created Observable 再次调用 Api,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41495729/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com