Angular中的可观察对象并订阅

时间:2020-03-07 03:23:25

标签: javascript angular rxjs observable

我是可观察的新手,我很难理解它的工作原理!

我有一些代码正在获取数据的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的任何好的教程或课程?

感谢您的帮助。

2 个答案:

答案 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上发帖,或查看其他人的解决方案。