【问题标题】:Observables in Angular and subscribeAngular 中的 Observable 和订阅
【发布时间】:2020-06-19 18:44:47
【问题描述】:

我是 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)
  }

关于我如何实现这一点的任何想法以及任何好的教程或课程,您可以指出我学习 Observables 的方法?

感谢您的帮助。

【问题讨论】:

    标签: javascript angular rxjs observable


    【解决方案1】:

    在您的fetch 方法之后,您似乎使用.then 暗示您有一个承诺而不是可观察的。我建议您使用服务中的 Rxjs 中的 from 方法将您的承诺转换为可观察的。或者,您可以从中创建一个主题。

    假设 this.vendorService.getVendors() 返回一个 observable,您必须像 @AliF50 在他的回答中建议的那样订阅它:

    //Inside your get method in your service:
    
    public getVendors(): Vendor[] {
      return from(fetch('./assets/data/vendor.json')).pipe(map(
        result => result.json()
      ));
    }
    

    现在您将通过调用 getVendors() 获得一个 observable。

    // 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 的新手,所以我会建议一个可以很好地改进您的应用程序的解决方案:

    如果你使用 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 之外,无需注入任何其他内容来解析您的供应商。

    注意: 上面的代码是在这里写的,并做了一些简化(例如组件类还远未完成),我跳过了导入语句。我尽量做到准确和完整,但如果您有疑问或遇到问题,请发表评论,然后我可以在必要时添加一些细节。

    【讨论】:

      【解决方案2】:

      试试:

      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 上发帖。

      【讨论】:

      • 感谢您的洞察力,我会继续努力。
      猜你喜欢
      • 2018-12-12
      • 2020-03-18
      • 2017-11-30
      • 2018-07-13
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-23
      相关资源
      最近更新 更多