gpt4 book ai didi

angular - 返回函数 Angular 2

转载 作者:搜寻专家 更新时间:2023-10-30 22:06:42 25 4
gpt4 key购买 nike

我有一个异步函数的问题。我有一项服务可以从 firebase 数据库中为我提供一些数据。其中一个函数返回一个值:

historialDeConsumi() {
this.item = this.af.database.object('/users/' + this.uid + '/admin', {
preserveSnapshot: true
});
this.item.subscribe(snapshot => {
this.hijosHistorialConsumi = snapshot.child('HisotialCons').val();

});
return this.hijosHistorialConsumi;
}

我从一个组件中调用这个函数:

ngOnInit() {
this.consumi = this.servicioData.historialDeConsumi();
}

我想将 this.consumi 与函数返回的值相匹配。我不知道该怎么做。

最佳答案

当然,您的代码将无法运行,因为您正试图返回尚不存在的内容。最直接的方法(但无论如何都不是最好的)是将未包装的可观察对象存储在服务变量中,然后提供一种检索它的方法。在下面,我使用简化/示例数据:

// Keep data locally.
private data;

// Listen to observable in constructor, and store locally.
constructor() {
this.item = this.af.database.object(path, {
preserveSnapshot: true
});
this.item.subscribe(snapshot => {
this.data = snapshot.val();
});
}

// Retrieve the data.
getData() { return this.data; }

但是请注意,使用快照的整个想法是不必要的。 AngularFire 返回可以直接订阅的可观察对象。因此:

constructor() {
this.item = this.af.database.object(path);
this.item.subscribe(data => this.data = data);
}

或者更简单地说,只是

constructor() {
this.af.database.object(path).subscribe(data => this.data = data);
}

但是,这种方法有一个严重的缺陷。调用访问器的任何人都将获得最新 值,但当他们持有该值时,如果有新值到达,他们将永远不会知道,并将继续使用旧值。或者,如果有人在第一次触发 observable 之前调用访问器,这完全有可能,他们最终会得到 undefined。 ,然后无法检索后续值。

因此,服务应该简单地返回 observable,组件将使用它。

// SERVICE
getData() { return this.af.database.object(path); }

// COMPONENT
public data;

ngOnInit() {
this.service.getData().subscribe(data => this.data = data);
}

<div>The data is {{data}}</div>

换句话说,我们“展开”ngOnInit 中的可观察对象,并将其展开的值存储在本地。这会像你想要的那样工作。但是,data 的初始值将是未定义的,直到 observable 发出它的第一个值,所以如果你试图访问数据的属性,假设它是一个对象:

<div>The name is {{data.name}}</div>

您将在尝试访问 name 时遇到错误属性(property) undefined .最明显的处理方法是使用 ?运算符,如

<div> The name is {{data?.name}}</div>

但是,您可能不想在模板中的所有地方都这样做,请记住 AOT 不支持 ? .令人不快的选择是将其包装在 <div *ngIf="data"> 中无处不在。

因此,首选的方法是将可观察对象保留为可观察对象直到最后一刻,并仅在必要时解包(订阅它),您可以按如下方式进行(使用命名变量的约定来保存可观察对象) $ 为清楚起见):

// COMPONENT
public data$: Observable<any>;

ngOnInit() {
this.data$ = this.service.getData();
}

<div>The data is {{data$ | async}}</div>

使用 async管道,隐式订阅。如果您想检索 data 上的属性, 然后

<div>The name is {{(data$ | async).name}}</div>

一切都会按预期进行。如果你想处理 observable 还没有发射的情况,那么

The name is
<div *ngIf="data$ | async as data"; else loading">{{data.name}}</div>
<ng-template #loading>not loaded yet</ng-template>

如果您想以某种方式预处理或操作可观察对象的值,而不是在服务或组件中展开它,然后对展开的值执行操作,请使用 map 操作可观察对象本身。 :

public firstName$;

ngOnInit() {
this.firstName$ = this.service.getData().map(data => data.name.split(' ')[0]);
}

然后在您的模板中使用映射的可观察对象

The first name is
<div *ngIf="firstName$ | async as firstName"; else loading">{{firstName}}</div>
<ng-template #loading>not loaded yet</ng-template>

总而言之,使用 AngularFire observables 以及所有 observables 的首选模式是尽可能长时间地将它们保留为 observables,通过将它们映射(或过滤)到新的 observables 来操作它们,避免展开它们并存储它们如果可能的话,它们在本地的值,最后在实际需要值的地方订阅,这在模板中很常见,订阅可以由 async 处理管道。

使用 async管道还有另一个主要优势。如果您在组件逻辑中显式订阅,则必须记住该订阅,然后在 ngOnDestroy 中取消订阅以避免内存泄漏。相比之下,Angular 会自动清除所有使用 async 隐式完成的订阅。给你吹。

关于angular - 返回函数 Angular 2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44027773/

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