Ioni c 3 Angular 5 Как получить данные и преобразовать их в Observable в ngOnInit - PullRequest
1 голос
/ 08 января 2020

Здравствуйте, мне нужно получить данные, поступающие из API и затем основанные на возврате ответа. Наблюдаемый в ngOnInit.

@ Редактировать В основном this.dayOverViewByGroup должен быть полностью загружен из API, когда возвращается в fetchChildrensData() => return Observable.of(this.dayOverViewByGroup).

@ Edit2 Добавлен код для getDayOverViewByGroupId

ngOnInit


ngOnInit() {
    const filter$: Observable<string> = this.filterControl.valueChanges.pipe(
      startWith(''),
      debounceTime(100), 
      distinctUntilChanged(),
      share()
    );
    this.dayOverViewByGroup$ = this.fetchChildrensData().pipe(
      map(days => days.map(day => (
        {
          ...day,
          filteredChildren$: filter$.pipe(this.filterFrom(day.children))
        }
      )))
    );
  }

fetchChildrensData

 fetchChildrensData(): Observable<any[]> {
    return Observable.of(this.dayOverViewByGroup)
 }

Функции, которые обрабатывают вызов API

getChildrens(date, groupId) {
    return this.attendanceService.getDayOverViewByGroupId(date, groupId).then(
      (res1: any) => {
        let dayOverViewByGroup = res1.mobile_employee_dayoverview;
        this.dayOverViewByGroup = dayOverViewByGroup;
        this.appFunctionCtrl.dismissLoader();  
      },
      (error) => console.log('Error occured in this.attendanceService.getDayOverViewByGroupId()', error)
    );

  }
getDayOverViewByGroupId(currentDate = null, groupId) {
    let that = this;
    return new Promise((resolve, reject) => {
      that.wsseGenerator.getWSSEHeader().then(header => {
        header.append('Access-Control-Allow-Origin', '*');
        header.append('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
        let options = new RequestOptions({ headers: header });
        let paramsData = {
          groupId: groupId,
          currentDate: currentDate
        };
        let params = that.serializeObject(paramsData);
        that.http.post(`${that.baseUrl}/dayoverview?${params}`, null, options).timeout(this.timeTimeout).subscribe((success: any) => {
          resolve(success);
        }, (err) => {

          this.appFunctionCtrl.dismissLoader();
          if (err.name == 'TimeoutError') {
            this.alert.present();
          }
          else {
            reject(err);
          }
        });
      });
    });
  }

1 Ответ

2 голосов
/ 08 января 2020

Вы должны вернуть Observable из вашей Службы, который не выдает никаких ошибок, чтобы вы могли напрямую использовать AsyncPipe в своем Компоненте для подписки (см. Также: Зачем обрабатывать ошибки с catchError, а не в обратном вызове ошибок подписки в Angular).

Преобразование вызовов Api, которые нельзя изменить, и возврат обещаний в Observables с помощью from и использование операторов Rx JS с этого момента (я предполагаю this.wsseGenerator.getWSSEHeader() это такой вызов).

Используйте switchMap для сопоставления с другой наблюдаемой, pluck или map для извлечения / преобразования возвращаемых данных, catchError для исправления ошибок и возврата наблюдаемой, которая не вызывает ошибок , finalize делать что-то, когда ваши Наблюдаемые ошибки или завершены.

В вашем Сервисе:

import { Observable } from "rxjs";
import { switchMap, map, timeout, catchError, finalize } from "rxjs/operators";

getDayOverViewByGroupId(currentDate = null, groupId): Observable<any> {
  return Observable.from(this.wsseGenerator.getWSSEHeader()).pipe( // use from to convert Promise to Observable
    switchMap(header => {
      header.append('Access-Control-Allow-Origin', '*');
      header.append('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
      let options = new RequestOptions({ headers: header });
      let paramsData = {
        groupId: groupId,
        currentDate: currentDate
      };
      let params = that.serializeObject(paramsData);
      // map to your http request
      return this.http.post(`${that.baseUrl}/dayoverview?${params}`, null, options);
    }),
    map(this.getRelevantData), // get relevant data from http response
    timeout(this.timeTimeout),
    catchError(error => { // handle errors and return an Observable that doesn't error
      console.log('Error occured in this.attendanceService.getDayOverViewByGroupId()', error);
      if (error.name == 'TimeoutError') {
          this.alert.present();
      }
      // you have to think about what default value you want to return on errors, null can be ok
      return Observable.of(null); 
    }),
    finalize(() => this.appFunctionCtrl.dismissLoader()) // do stuff on error and complete
  );
}

private getRelevantData(response): any { // <-- don't return 'any' in your real code, create interfaces to type your data if you can
  let dayOverViewByGroup = response.mobile_employee_dayoverview;
  dayOverViewByGroup.forEach(element => {
    // do your thing
  }
  console.log('dayOverViewByGroup', dayOverViewByGroup)
  return dayOverViewByGroup;
}

В вашем Компоненте:

ngOnInit() {
  this.dayOverViewByGroup$ = this.attendanceService.getDayOverViewByGroupId( .. ).pipe( 
    // If the Observable from your service can emit 'null' and you do
    // map(days => days.map(..)) you will get an error 
    // so you might have to handle this case here

    // 1. Option: filter out 'null' and 'undefined' values before your 'map' and don't emit anything
    filter(Boolean)

    // 2. Option: handle 'null' and 'undefined' in your map function
    map(days => {     
      if (days) {
        days.map( .. )
      } else {
        // do something else or don't do anything at all, i.e. remove the else case
      }
    })
  )
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...