如何从Observable返回数组

时间:2019-07-09 07:16:24

标签: angular typescript promise observable

嗨,我有一个应返回Array的函数,在下面的函数中,this.cordovaFile.readAsArrayBuffer(this.cordovaFile.dataDirectory, storageId)实际上返回了一个Promise Array,我将其转换为Observable并将其存储到timesheetArray变量中,现在将{{1}它将返回Observable数组,但我只想返回一个Array。下面是代码

请帮助,如果它只返回一个数组,则我不需要在任何地方更改它,因为此功能在整个应用程序中都使用

timesheetArray

还有一个示例,为什么我要返回一个数组但不可观察

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

3 个答案:

答案 0 :(得分:2)

我认为您没有考虑正确的方向。 readAsArrayBuffer是一个异步调用。因此,它返回了一个承诺。

您不应该简单地从TimesheetModel[]方法返回一个getAllTimesheets()

相反,您应该返回一个Observable<TimesheetModel[]>。但是无论您在何处调用此getAllTimesheets()方法,都必须进行一些小的更改。

由于它返回了Observable<TimesheetModel[]>,因此在所有这些地方都必须从subscribegetAllTimesheets()。否则,您必须使用Observable管道在模板中阅读此async

我建议后者。

因此,请对您的getAllTimesheets()方法进行以下更改。

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 :(得分:1)

请勿将您的全部承诺记录为可观察的。设置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);
  }
}

答案 2 :(得分:-1)

您可以简单地使用as []

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