0

I have a little problem with my function, one of the params that I want to set I'm getting from the http request. The problem is that the final data from method below is recalculated in one of the components, and when it happens the result of request is still null. When the response come it's not triggering onChanges so I can't recalculate this data again, and doCheck triggering "too often".

updateData(componentRecords: ComponentRecord[], importSourceGroup?: ImportSource[], isImportSource = false, component: DiaryNode = null) {
    const recordData = [];
    const records = isImportSource ? importSourceGroup : componentRecords;
    for (const record of records) {
      const recordRow: any = record.ID === 'addingRow' ? record : {
        ID: record.ID,
        InputTypeID: record.InputTypeID,
        SubRecords: record.SubRecords,
        attachmentField: record.Fields ? record.Fields.find(({Type}) => Type === DiaryFieldType.ATTACHMENT) : null,
        documentsFolder: null,
        DateUpdated: null,
        ComponentInstanceID: null,
        linkedUnits: {},
        recordRef: record
      };

      if (record.ID !== 'addingRow') {

        if (isImportSource) {
          recordRow.DateUpdated = (record as ImportSource).DateUpdated;
          recordRow.ComponentInstanceID = (record as ImportSource).ComponentInstanceID;
        }

        if (recordRow.attachmentField && recordRow.attachmentField.Value) {
          this.subManager.add(this.documentsApiService
            .getFileDetailsByFolderID(recordRow.attachmentField.Value)
            .subscribe((documents: DocumentsFolder) =>
              recordRow.documentsFolder = documents));
        }

        if (record.Fields) {
          for (const field of record.Fields) {
            const label = field.Label;
            recordRow[label] = field.Type === DiaryFieldType.INTEGER ? parseInt(field.Value, 10) : field.Value;
            const schema = component && component.Schema && component.Schema.find(diaryFormField => diaryFormField.Label === label);
            if (schema && schema.LinkedUnit) {
              recordRow.linkedUnits[label] = schema.LinkedUnit.Attributes.List.PickListItems[0].Label;
            }
          }
        }
      }
      recordData.push(recordRow);
    }
    return recordData;
  }

The part that is async is

        if (recordRow.attachmentField && recordRow.attachmentField.Value) {
          this.subManager.add(this.documentsApiService
            .getFileDetailsByFolderID(recordRow.attachmentField.Value)
            .subscribe((documents: DocumentsFolder) =>
              recordRow.documentsFolder = documents));
        }

So I don't know what is the best solution for this but I was wondering if it's possible to wait here for the response, and go furthure when it comes.

What do you think?

D.Zet
  • 539
  • 3
  • 6
  • 19

1 Answers1

1

In short the property cannot be assigned synchronously using the asynchronous HTTP request. Instead you need to make entire paradigm asynchronous. Then you could subscribe to the function updateData() to fetch the array.

Additionally you could use RxJS forkJoin function to combine multiple parallel observables. Try the following

updateData(
  componentRecords: ComponentRecord[], 
  importSourceGroup?: ImportSource[], 
  isImportSource = false, 
  component: DiaryNode = null
): Observable<any> {                      // <-- return `Observable` here
  const records = isImportSource ? importSourceGroup : componentRecords;

  return forkJoin(                        // <-- use `forkJoin` to combine multiple parallel observables
    records.map(record => {
      const recordRow: any = record.ID === 'addingRow' ? record : {
        ID: record.ID,
        InputTypeID: record.InputTypeID,
        SubRecords: record.SubRecords,
        attachmentField: record.Fields ? record.Fields.find(({Type}) => Type === DiaryFieldType.ATTACHMENT) : null,
        documentsFolder: null,
        DateUpdated: null,
        ComponentInstanceID: null,
        linkedUnits: {},
        recordRef: record
      };

      if (record.ID !== 'addingRow') {
        if (isImportSource) {
          recordRow.DateUpdated = (record as ImportSource).DateUpdated;
          recordRow.ComponentInstanceID = (record as ImportSource).ComponentInstanceID;
        }

        if (record.Fields) {
          for (const field of record.Fields) {
            const label = field.Label;
            recordRow[label] = field.Type === DiaryFieldType.INTEGER ? parseInt(field.Value, 10) : field.Value;
            const schema = component && component.Schema && component.Schema.find(diaryFormField => diaryFormField.Label === label);
            if (schema && schema.LinkedUnit) {
              recordRow.linkedUnits[label] = schema.LinkedUnit.Attributes.List.PickListItems[0].Label;
            }
          }
        }

        if (recordRow.attachmentField && recordRow.attachmentField.Value) {
          return this.documentsApiService.getFileDetailsByFolderID(recordRow.attachmentField.Value).pipe(     // <-- return the HTTP request
            map((documents: DocumentsFolder) => ({ ...recordRow, recordRow.documentsFolder: documents }))     // <-- spread operator to append new value to object
          );
        }

        return of(recordRow);       // <-- use `of()` to return as observable
      }

      return of(recordRow);       // <-- use `of()` to return as observable
    })
  );
}

See here to learn more about fetching info from async request.

Michael D
  • 20,838
  • 4
  • 12
  • 37