簡體   English   中英

Angular 中的 Observables 和訂閱

[英]Observables in Angular and subscribe

我是 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 的任何好的教程或課程?

謝謝你的幫助。

在您的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,您還可以查看路由器的解析功能。 在此處的文檔中閱讀更多內容

為您的供應商創建一個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 ,無需注入任何其他內容來解決您的供應商問題。

注意:上面的代碼寫在這里並簡化了一點(例如組件類遠未完成),我跳過了導入語句。 我試圖盡可能准確和完整,但如果您有疑問或遇到問題,請發表評論,然后我可以在必要時添加一些詳細信息。

嘗試:

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但可以學習新語法,但可以學習新語法)語法,沒那么難。

將 observable 視為可以用運算符修改的數據流。 要正確學習它,您將不得不親自動手並不斷嘗試解決與之相關的問題。 當您遇到困難或查看其他人的解決方案時,請繼續在 Stackoverflow 上發帖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM