Eddie
Eddie

Reputation: 31

Typescript async function with foreach, inside foreach, calling another async function

recently i stumbled a problem with an async function.

I am using 2 functions, both of them are async. Problem is the fact that the return value is a promise, since i cant await for it inside the foeach loops. I have tried making the both foreach async, but that does not work as it feeds me bogus data.

private getAllProperties = async (props?: IPageDetailsProps) => {
props = props || this.props;
let web = new Web(props.context.pageContext.web.absoluteUrl);
let id = 2;
let pageProps = await web.lists.getByTitle("Site Pages").items.filter(`Id eq '${id}'`).get();
let fieldProps = await web.lists.getByTitle("Site Pages").fields.filter(`Group eq 'Template Columns' or InternalName eq 'Title' or InternalName eq 'Created' or InternalName eq 'Author' or InternalName eq 'Modified' or InternalName eq 'Editor'`).get();
let regionalSettings = await web.regionalSettings.get();
let fieldsList: Array<any> = [];
let obj = JSON.parse(props.fields.toString());

fieldProps.forEach(value => {
  obj.forEach(field => {
    if (field === value.InternalName) {
      let item: any = {};
      item.title = value.Title;
      item.internalName = value.InternalName;
      item.typeAsString = value.TypeAsString;
      if (item.typeAsString === "DateTime") {
        let formatOptions: Intl.DateTimeFormatOptions = {};
        formatOptions.hour12 = !regionalSettings.Time24;
        let date = new Date(pageProps[0][field]);
        item.Data = date.toLocaleString(regionalSettings.LocaleId, formatOptions);
      }
      if (item.typeAsString === "Text" || item.typeAsString === "Note") {
        let text = pageProps[0][field];
        item.Data = text;
      }
      if (item.typeAsString === "User") {
        let personId = field + "Id";
        let user = this.getPersonFromId(pageProps[0][personId])
        item.Data = user;
       // Problem is here, by the fact that the return value from 
       // getPersonFromId is a promise, 
       // since i cant await for it here.
       // I have tried making the both foreach async, but that does not work 
       // as it feeds me bogus data.
       // What i want to do is not do anything until i have an answer
      }
      if (item.typeAsString === "TaxonomyFieldType") {
        item.Data = pageProps[0][field].Label;
      }
      if (item.typeAsString === "TaxonomyFieldTypeMulti") {
        let items = pageProps[0][field];
        let terms = "";
        items.forEach(element => {
          terms += element.Label + "   ";
        });
        item.Data = terms;
      }
      fieldsList.push(item);
    }
  });
});

Function 2

private getPersonFromId = async (id: number) => {
let queryUrl = this.props.context.pageContext.site.absoluteUrl + `/_api/web/getuserbyid(${id})`;
const spSearchConfig: ISPHttpClientConfiguration = {
  defaultODataVersion: ODataVersion.v3
};
let personResponse = await this.props.context.spHttpClient.get(queryUrl, SPHttpClient.configurations.v1.overrideWith(spSearchConfig));
let personResult = await personResponse.json();

let person: any = {};
person.name = personResult.Title;
person.mail = personResult.Email;

return person;

}

Upvotes: 1

Views: 3616

Answers (1)

ethan.roday
ethan.roday

Reputation: 2635

Async functions don't play well with forEach, since forEach has no mechanism to wait for the async callback to be finished in any given iteration. You'll need to do one of the following:

Upvotes: 3

Related Questions