这让我觉得它应该可行,但我收到了一个模板错误:Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
模板:
<div class="block-header">
<h2>{{ policyName }}</h2>
</div>
<div *ngFor="let p of policies | async" class="card event-card">
<div class="card-header">
<h2>{{ p.title }}</h2>
</div>
<div class="card-body card-padding">
<div [markdown]="p.description"></div>
</div>
</div>
组件:
export class PoliciesComponent implements OnInit {
name: string = 'policies';
//public policies: Policy[];
public policies: Observable<Policy>;
constructor(
private policyService: PolicyService,
private route: ActivatedRoute) { }
ngOnInit(): void {
// this.route.params is an observable of the child (category) routes under /policies
this.route.params.subscribe((p: Params) => this.loadPolicies(p['category']))
}
loadPolicies(category: string): void {
let policyCategory = PolicyCategory.ClubPolicy;
if (category === 'rules') {
policyCategory = PolicyCategory.LocalRule;
} else if (category === 'handicaps') {
policyCategory = PolicyCategory.Handicaps;
}
this.policies = this.policyService.loadPolicies(policyCategory);
// this.policies = [];
// this.policyService.loadPolicies(policyCategory).subscribe(p => this.policies.push(p))
}
}
服务:
loadPolicies(category: PolicyCategory): Observable<Policy> {
return this.dataService.getApiRequest('policies')
.mergeAll() // turn Observable<any> where any=collection into Observable
.map((p: any) => new Policy().fromJson(p))
.filter((policy: Policy) => policy.category === category)
}
使用替换代码(在组件中的注释中),一切正常,但我将不得不取消订阅订阅。我觉得我做得对,但我的浏览器不同意。
对于异步如何与Observable一起使用,我有什么误解?
答案 0 :(得分:0)
“我误解了什么?”这个问题的答案。太过分了。
我认为,最根本的是,在尝试采用更具反应性的编程风格时,要理解服务的作用。它应该做的不仅仅是通过。
根据Cory Rylan的this post阅读,我得出的结论是,我的服务应该从api管理数据的方式完全不同。最后的概述部分特别值得一读。
因此,虽然我没有在原帖中重新设计该服务,但我确实认为这是一个用于CRUDdy服务的好模式。该服务有一个我的组件订阅的数据存储。这些操作会改变数据存储,并且随着可观察数据的奇迹,它们会在商店因这些操作而发生变化时自动更新。
将“ProfilerJob”替换为您管理的任何对象:
@Injectable()
export class ProfilerJobService {
private resource: string = 'profile';
private _jobs: BehaviorSubject<ProfilerJob[]>;
private store: {
items: ProfilerJob[]
};
constructor(private dataService: DataService) {
this.store = {
items: []
};
this._jobs = <BehaviorSubject<ProfilerJob[]>>new BehaviorSubject([]);
}
get jobs(): Observable<ProfilerJob[]> {
return this._jobs.asObservable();
}
selectJob(id: string): Observable<ProfilerJob> {
if (id === 'new') {
return Observable.of(new ProfilerJob());
}
return this._jobs.map(jobs => {
let job = jobs.find(item => item.id === id);
return _.clone(job);
});
}
loadJobs(filter: JobFilter = null): void {
let url = this.resource;
let params: any;
if (filter) {
url = url + '/search';
params = filter.toSearchApi();
}
this.dataService.getData(url, params).subscribe(data => {
this.store.items.length = 0;
data.forEach((d: any) => this.store.items.push(new ProfilerJob().fromJson(d)));
this._jobs.next(_.cloneDeep(this.store).items);
});
}
loadJob(id: string): void {
this.dataService.getData(`${this.resource}/${id}`).subscribe(json => {
let found = false;
this.store.items.forEach((item, index) => {
if (item.id === json.id) {
this.store.items[index] = new ProfilerJob().fromJson(json);
found = true;
}
});
if (!found) {
this.store.items.push(new ProfilerJob().fromJson(json));
}
this._jobs.next(_.cloneDeep(this.store).items);
});
}
addJob(job: ProfilerJob): Observable<void> {
return this.dataService.postData(this.resource, job.toJson())
.do((json: any) => {
this.loadJob(json.id);
});
}
updateJob(job: ProfilerJob): Observable<void> {
return this.dataService.putData(`${this.resource}/${job.id}`, job.toJson())
.do(() => {
this.loadJob(job.id);
});
}
deleteJob(job: ProfilerJob): Observable<void> {
return this.dataService.deleteData(`${this.resource}/${job.id}`)
.do(() => {
let idx = this.store.items.findIndex(j => j.id === job.id);
this.store.items.splice(idx, 1);
this._jobs.next(_.cloneDeep(this.store).items);
});
}
}