Наблюдаемые в Angular и подписаться - PullRequest
1 голос
/ 07 марта 2020

Я новичок в наблюдении, и мне очень тяжело понять, как это работает!

У меня есть код, который загружает файл JSON для данных, но я не получаю его на свой ngOninit, я предполагаю, что это потому, что код асинхронный. Я хочу настроить наблюдаемую подписку на данные, как только они поступят, но я совершенно новичок в наблюдаемой.

Вот код;

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

Любые идеи о том, как я могу сделать sh это и любые хорошие уроки или уроки, на которые вы можете указать мне для изучения Observables?

Спасибо за вашу помощь.

Ответы [ 2 ]

3 голосов
/ 07 марта 2020

После вашего fetch метода вы, похоже, используете .then, предполагая, что у вас есть обещание, а не наблюдаемое. Я предлагаю вам преобразовать свое обещание в наблюдаемое с помощью метода from из Rx js внутри вашего сервиса. В качестве альтернативы вы можете создать из него тему.

Если предположить, что 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, я предложу решение, которое может быть хорошее улучшение для вашего приложения:

Если вы используете наблюдаемые и 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, для разрешения ваших поставщиков.

Примечание: приведенный выше код был написан здесь и немного упрощен (например, класс компонента далек от завершено) и я пропустил операторы импорта. Я старался быть максимально точным и полным, но оставляю комментарий, если у вас есть вопросы или возникают проблемы, тогда я могу добавить некоторые детали, где это необходимо.

1 голос
/ 07 марта 2020

Попробуйте:

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, когда застряли, или посмотрите на решения других людей.

...