typescriptsharepointframework

SharePoint Framework & TypeScript & wait until all promises finishes before returning to client


I have a question about waiting for promises to resolve before return a value back to the client.

I'm working with the SharePoint Framework to get a collection of list and document library names from my config list and then I'm using these names (the list and document library names) to call back to SharePoint to retrieve the list items for each list and document library.

Provided below is my code to retrieve the names of the list and document libraries that I will use to retrieve the list items:

private _getListData(): Promise<ISPLists> {
    let listName:string = "SPListDisplayUIConfig";
    let currentUrl      = this.context.pageContext.web.absoluteUrl + `/_api/web/lists/GetByTitle('`+listName+`')/Items`;
    var formatedResponse: ISPLists = { value: [] };
    return this.context.spHttpClient.get(currentUrl, SPHttpClient.configurations.v1)
           .then((response: SPHttpClientResponse) => {
             //Extract the response.json object.
             return response.json().then((responseFormated: any) => {
              //Evaluate the response.               
              responseFormated.value.map((object: any, i: number) =>{
                var listItems: ListObjects = { value: [] };
                var spListItem: ISPList = {
                    Id: object['ID'],
                    Title: object['Title'],
                    DisplayListTitle: object['DisplayListTitle'],
                    RowCount: object['RowCount'],
                    SortOrder: object['SortOrder'],
                    ShowOnHomePage: object['ShowOnHomePage'],
                    ListType: '',
                    ListItems:  listItems
                };
                formatedResponse.value.push(spListItem); 
               });
               //Create a local list and store all the this._getListItems(Title) calls into the array, then pass the local array into the Promise.all method to execute each
               //method. In the return result (then), extract each list item and store into the spListItem.ListItem property.
               let promisesMethods:any = [];
               formatedResponse.value.forEach((item:ISPList) => {
                  let listName:string = item.Title;
                  promisesMethods.push(this._getListItems(listName));
               });
               Promise.all(promisesMethods).then((result:any) => {
                  console.log("Here");
               });
               console.log("Here 1")
               return formatedResponse;
             })
           })
   }

The this._getListItems method retrieves the list items for each listname.

let promisesMethods:any = [];
               formatedResponse.value.forEach((item:ISPList) => {
                  let listName:string = item.Title;
                  promisesMethods.push(this._getListItems(listName));
               });
               Promise.all(promisesMethods).then((result:any) => {
                  console.log("Here");
               });
               console.log("Here 1")

This is the this._getListItems definition:

private _getListItems(ListName: string): Promise<ListObjects>{
      let currentUrl = this.context.pageContext.web.absoluteUrl + `/_api/web/lists/GetByTitle('`+ListName+`')/Items`; 
      return this.context.spHttpClient.get(currentUrl, SPHttpClient.configurations.v1)
           .then((response: SPHttpClientResponse) => {
             return response.json().then((responseFormated: any) => {
              var formatedResponse: ListObjects = { value: []};  
              responseFormated.value.map((object: any, i: number) =>{
                var spListItem: ListObject = {
                          Title: object['Title'],
                          ItemUrl: "",
                          ItemType: "",
                          FileType: "",
                          Id: object['ID']
                 };
                 formatedResponse.value.push(spListItem);
               });

               return formatedResponse;
             })
           })
   }

In the code below the console.log("Here 1") is called before the console.log("Here"). I need to get all the list items for each list and Library before I return the results back to the client.

let promisesMethods:any = [];
               formatedResponse.value.forEach((item:ISPList) => {
                  let listName:string = item.Title;
                  promisesMethods.push(this._getListItems(listName));
               });
               Promise.all(promisesMethods).then((result:any) => {
                  console.log("Here");
               });
               console.log("Here 1")
               return formatedResponse;

Thank you


Solution

  • Just continue your code inside the then block, and in the outer block, return the promise corresponding to this then block to the caller. Something like this:

      private _getListData(): Promise<ISPLists> {
        let listName:string = "SPListDisplayUIConfig";
        let currentUrl      = this.context.pageContext.web.absoluteUrl + `/_api/web/lists/GetByTitle('`+listName+`')/Items`;
        var formatedResponse: ISPLists = { value: [] };
        return this.context.spHttpClient.get(currentUrl, SPHttpClient.configurations.v1)
               .then((response: SPHttpClientResponse) => {
                 //Extract the response.json object.
                 return response.json().then((responseFormated: any) => {
                  //Evaluate the response.               
                  responseFormated.value.map((object: any, i: number) =>{
                    var listItems: ListObjects = { value: [] };
                    var spListItem: ISPList = {
                        Id: object['ID'],
                        Title: object['Title'],
                        DisplayListTitle: object['DisplayListTitle'],
                        RowCount: object['RowCount'],
                        SortOrder: object['SortOrder'],
                        ShowOnHomePage: object['ShowOnHomePage'],
                        ListType: '',
                        ListItems:  listItems
                    };
                    formatedResponse.value.push(spListItem); 
                   });
                   //Create a local list and store all the this._getListItems(Title) calls into the array, then pass the local array into the Promise.all method to execute each
                   //method. In the return result (then), extract each list item and store into the spListItem.ListItem property.
                   let promisesMethods:any = [];
                   formatedResponse.value.forEach((item:ISPList) => {
                      let listName:string = item.Title;
                      promisesMethods.push(this._getListItems(listName));
                   });
                   return Promise.all(promisesMethods).then((result:any) => {
    //             ^^^^^^
                      console.log("Here");
                      // Any more necessary processing
                      return /* whatever result you want */;
                   });
                 })
               })
       }