我是可观察的新手,我很难理解它的工作原理!
我有一些代码正在获取数据的JSON文件,但是我没有在ngOninit上获取它,我假设它是因为代码是异步的。我想设置一个observable,以便一旦数据进入就订阅数据,但是对于observable来说是全新的。
这是代码;
fetch('./assets/data/vendor.json').then(res => res.json())
.then(data => {
this.vendorData = data.vendors;
this.vendorService.setVendors(this.vendorData);
});
}
ngOnInit() {
this.filteredVendor = this.vendorService.getVendors();
this.isfiltered = true;
console.log(this.filteredVendor)
}
关于如何实现此目标的任何想法,以及您可以向我介绍以了解Observable的任何好的教程或课程?
感谢您的帮助。
答案 0 :(得分:3)
在使用fetch
方法之后,您似乎使用.then
表示您有一个诺言而不是可观察的。我建议您使用服务内部Rxjs的from
方法将诺言转换为可观察的。或者,您可以从中创建一个主题。
假设this.vendorService.getVendors()
返回一个可观察值,则您必须像在其答案中建议的@ AliF50一样订阅它。
//Inside your get method in your service:
public getVendors(): Vendor[] {
return from(fetch('./assets/data/vendor.json')).pipe(map(
result => result.json()
));
}
现在,从对getVendors()
的呼叫中您将得到一个可观察到的东西。
// it is good practice to use a dollar sign at the end of a variable when its value is an observable
public ngOnInit() {
const vendors$ = this.vendorService.getVendors();
vendors$.subscribe((vendors: Vendor[]) => {
// The argument defined assuming the vendors observable resolves in an array of Vendor
// this.filteredVendor will be set when the observable emits the result
this.filteredVendor = vendors;
})
}
由于您是Angular中新的可观察对象,因此我建议一种解决方案,可能会对您的应用程序有很大的改善:
如果您使用Observables和Angular,还可以研究路由器的解析功能。了解更多in the documentation here。
为您的供应商创建VendorResolver
:
@Injectable({ providedIn: 'root' })
export class VendorResolver implements Resolve<Vendor> {
constructor(private vendorService: VendorService) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<Vendor[]> {
return this.vendorService.getVendors();
}
}
在您的VendorService
内:
public getVendors(): Observable<Vendor[]> {
// TODO: get fetch method available in the service, not sure where it comes from
// create a fetch$ observable using RxJs from (needs to be imported)
// from will convert your promise to an observable
const fetch$ = from(fetch('./assets/data/vendor.json'));
// pipe and map will map the observable result, return desired vendors from the map
return fetch$.pipe(map(result => {
const data = result.json();
return data.vendors;
}));
}
现在您可以按照自己的路线做
@NgModule({
imports: [
RouterModule.forRoot([
{
path: 'vendors',
component: VendorComponent,
resolve: {
vendors: VendorResolver
}
}
])
],
exports: [RouterModule]
})
export class AppRoutingModule {}
当路由到“供应商”路由时,路由器将自动使用VendorsResolver
解决您的供应商。请注意,如果无法解决,路由将无法完成。
在您的VendorComponent
内,您可以直接从路线快照数据访问供应商:
class VendorsComponent {
constructor(private route: ActivatedRoute) {
}
public ngOnInit() {
this.filteredVendor = this.route.snapshot.data.vendors;
}
}
这使您组件中的代码非常少;无需注入ActivatedRoute
以外的任何其他东西来解决您的供应商。
注意: 上面的代码是在此处编写的,并进行了一些简化(例如,组件类还远远不够完整),我跳过了import语句。我试图做到尽可能准确和完整,但是如果您有任何疑问或遇到问题,请发表评论,然后在必要时我可以添加一些详细信息。
答案 1 :(得分:1)
尝试:
ngOnInit() {
this.vendorService.getVendors().subscribe(
venders => this.filteredVendor = venders;
this.isFiltered = true;
console.log(this.filteredVendor);
);
}
至于学习,我将继续练习并寻找如何做事。这些教程可能已经过时,但对我有好处(https://egghead.io/courses/introduction-to-reactive-programming?fbclid=IwAR1I2--NX82Lg1iCvzLIx4vPtEw_PIbWid7eqboBT9RWI_h0G2zfE3i6hDA),但是语法可能有些过时,但是要学习新语法,并不难。
将可观察变量视为可以由运算符修改的数据流。要正确学习它,您将不得不弄脏手,并继续尝试解决与之相关的问题。遇到困难时,请继续在Stackoverflow上发帖,或查看其他人的解决方案。