Как вернуть массив из наблюдаемой - PullRequest
2 голосов
/ 09 июля 2019

Привет, у меня есть функция, которая должна возвращать Array, в приведенной ниже функции this.cordovaFile.readAsArrayBuffer(this.cordovaFile.dataDirectory, storageId) фактически возвращает массив Promise, который я преобразовываю в Observable и сохраняю в переменную timesheetArray, а теперь timesheetArray возвращает массив Observable но я просто хочу вернуть только массив. Ниже приведен код

Пожалуйста, помогите, если он возвращает только массив, мне не нужно никуда его менять, потому что эта функция используется в приложении

public getAllTimesheets(): TimesheetModel[] {
  const storageId = TIMESHEET_KEYS.ALL_TIMESHEET;

  const timesheetArray = from(
    this.cordovaFile
    .readAsArrayBuffer(this.cordovaFile.dataDirectory, storageId)
    .then((compressedTimesheet) => {
      const start = moment();
      const uint8array = new Uint8Array(compressedTimesheet);
      const jsonTimeSheet = this.LZString.decompressFromUint8Array(uint8array);
      this.log.debug(`LocalStorageMaterialService: getMaterials() from files: Decompression took ${moment().subtract(start.valueOf()).valueOf()} ms`);
      return <TimesheetModel[] > JSON.parse(jsonTimeSheet) || [];
    })
    .catch((error) => {
      this.log.debug('LocalStorageMaterialService: Retrieving materials from file storage was not possible: ', JSON.stringify(error));
      return [];
    })
  )
  timesheetArray.subscribe((timesheet) => {
    // here how to return an Array ??
  });
}

и только один пример, почему я хочу вернуть массив, но не наблюдаемый

let matchedTimesheet = _.find<TimesheetModel>(this.getAllTimesheets() ,
(timesheet) => travelToDate 
&& timesheet.startOfWork.isSame(travelToDate.startDate.value, 'days')
            ); ```

here in the above code it is expecting an array but not Observable., I can do it by subscribing here also , but if the function returns an array instead of  observable, then i need to change everywhere

Ответы [ 3 ]

2 голосов
/ 09 июля 2019

Я не думаю, что вы думаете об этом в правильном направлении.readAsArrayBuffer - асинхронный вызов.Следовательно, он возвращает обещание.

Вы не должны просто возвращать TimesheetModel[] из вашего getAllTimesheets() метода.

Скорее, вы должны возвращать Observable<TimesheetModel[]>.Но вам придется вносить небольшие изменения, где бы вы ни вызывали этот getAllTimesheets() метод.

Поскольку он возвращает Observable<TimesheetModel[]>, вам придется либо subscribe getAllTimesheets()эти места.Или вам нужно будет прочитать Observable в своем шаблоне, используя async трубу.

Я бы порекомендовал последнее.

Поэтому внесите следующие изменения в getAllTimesheets()method.

public getAllTimesheets(): Observable<TimesheetModel[]> {
  const storageId = TIMESHEET_KEYS.ALL_TIMESHEET;
  return from(
    this.cordovaFile
    .readAsArrayBuffer(this.cordovaFile.dataDirectory, storageId)
    .then((compressedTimesheet) => {
      const start = moment();
      const uint8array = new Uint8Array(compressedTimesheet);
      const jsonTimeSheet = this.LZString.decompressFromUint8Array(uint8array);
      this.log.debug(`LocalStorageMaterialService: getMaterials() from files: Decompression took ${moment().subtract(start.valueOf()).valueOf()} ms`);
      return <TimesheetModel[] > JSON.parse(jsonTimeSheet) || [];
    })
    .catch((error) => {
      this.log.debug('LocalStorageMaterialService: Retrieving materials from file storage was not possible: ', JSON.stringify(error));
      return [];
    })
  );
}

И затем, где бы вы его не использовали, если вы subscribe обращаетесь к нему:

// unsubscribe this subscription on ngOnDestroy()
const subscription = getAllTimesheets()
  .subscribe(timesheetData => {
    // Here you'll get that data.
  })
1 голос
/ 09 июля 2019

Не регистрируйте все свое обещание как наблюдаемое.Установите BehaviorSubject и обновите тему, указав результат своего обещания, используя .next().Затем вы можете подписаться на этот результат.

Предполагая, что это все в службе, вы можете настроить его следующим образом:

@Injectable({ providedIn: 'root' })
export class TimesheetsService {
  /**
   * Create a new behavior subject with an empty array. This is what you will
   * subscribe to from outside of your service.
   */
  public timesheets$: BehaviorSubject<TimesheetModel[]> = new BehaviorSubject([]);

  constructor() {
    // Call your service method to GET your data.
    this.getAllTimesheets();
  }

  /**
   * This method is how you will update your behavior subject and can be called
   * from outside the service each time you want to update your result.
   */
  public getAllTimesheets() {
    return this.cordovaFile
      .readAsArrayBuffer(this.cordovaFile.dataDirectory, storageId)
      .then((compressedTimesheet) => {
        const uint8array = new Uint8Array(compressedTimesheet);
        const jsonTimeSheet = this.LZString.decompressFromUint8Array(uint8array);
        // On success, update the behavior subject with the result of your call.
        return timesheets$.next(JSON.parse(jsonTimeSheet));
      })
      // Or on error, update the behavior subject.
      .catch(() => timesheets$.next([]));
  }
}

Затем в вашем компоненте вы можете подписаться на ваш result$ наблюдаемый.

export class YourComponent implements OnInit {
  timesheets: TimesheetModel[];

  constructor(private timesheetsService: TimesheetsService) {
    // Optionally call your service method again to GET fresh data.
    this.timesheetsService.getAllTimesheets();
  }

  ngOnInit() {
    /**
     * Subscribe to the result of your service call and pass the result to a
     * reference to be consumed by your component.
     */
    this.timesheetsService.timesheets$
      .subscribe((timesheets) => this.timesheets = timesheets);
  }
}
0 голосов
/ 09 июля 2019

Вы можете просто использовать as []

timesheetArray.subscribe((timesheet) => {
    const time_sheet = timesheet as [];
});
...