递归ajax查询

I was hoping that someone may be able to give me a pointer on how to achieve the following.

Currently, I have:

  • A JS function: A jQuery AJAX query that will get items from a SharePoint custom list.

  • A JS function: it will put the list results in to a datatable.

  • A JS function, that can turn an InitatorId into the real name of a user (GetDisplayName).

    function GetDisplayName(userid) {
    var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")";
    
    var requestHeaders = { "accept" : "application/json;odata=verbose" };
    
    $.ajax({
      url : requestUri,
      contentType : "application/json;odata=verbose",
      headers : requestHeaders,
      success : GetDisplayNameSuccess,
      error : GetDisplayNameFail
      });
    }
    
    
       function populateMyOutstandingItems() {
    
          SP.SOD.executeFunc("sp.js", "SP.ClientContext", function() {
            SP.SOD.executeFunc("sp.runtime.js", "SP.ClientContext", function() {
              var context = SP.ClientContext.get_current();
              var queryUrl = "https://companyname.sharepoint.com/subsite/_api/Web/Lists/getbytitle('Read%20Requests')/GetItems"; //change the Url
              var camlXML = "<Query><Where><And><Eq><FieldRef Name='ReaderId' LookupId='True' /><Value Type='Integer'>" + _spPageContextInfo.userId + "</Value></Eq><Neq><FieldRef Name='Read' /><Value Type='Text'>YES</Value></Neq></And></Where></Query>"
    
              var requestData = { "query" :
                   {"__metadata": 
                      { "type": "SP.CamlQuery" }
                      , "ViewXml": camlXML
                   }
                 };
    
              return jQuery.ajax({
                url: queryUrl,
                type: "POST",
                data: JSON.stringify(requestData),
                headers: {
                    "X-RequestDigest": $("#__REQUESTDIGEST").val(),
                    "Accept": "application/json; odata=verbose",
                    "Content-Type": "application/json; odata=verbose"
                },
                success: onQuerySuccessMyOutstandingItems,
                error: onQueryErrorMyOutstandingItems
              });
            });
          });
    }
    
    function onQuerySuccessMyOutstandingItems(data) {
    var jsonData = data.d.results
    console.log(jsonData)
    $("#resultsDivMyOutstandingItems").dataTable( {
        "data" : jsonData,
        columns: [
            { data: "Document_x0020_Name" },
            { data: "Document_x0020_Library_x0020_Nam" },           
            { data: "Request_x0020_Made_x0020_Date" },
            { data: "InitatorId" },
            { data: "Request_x0020_ReadBy_x0020_Date" }, ],
              order: [[3, "asc"]]
    } ); }
    

At the moment, in the datatable, I have the InitatorID (ie. 30) but I would like to have the real name of the user in the table.

I understand some type of recursive AJAX query will be needed, but I'm not sure what the best way forward would be to achieve this, and was hoping that someone would be able to point me in the right direction.

After reading a bit about chained requests, I tried the code below, but it's wrong I guess, since Chrome complains of an 'unexpected ending':

      var request = $.ajax({
        url: queryUrl,
        type: "POST",
        data: JSON.stringify(requestData),
        headers: {
            "X-RequestDigest": $("#__REQUESTDIGEST").val(),
            "Accept": "application/json; odata=verbose",
            "Content-Type": "application/json; odata=verbose"
                }
        }),
        chained = request.then(function( data ) {
            return $.ajax( spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + data.InitatorId + ")",
            { data: { user: data.Title }} )
        });

        chained.done(function( data ) {
          console.log(data)
        });

In short, what is the best to achieve what I'm trying to do?

Many thanks Glen

I am not sure I completely understand what you're asking, so here's my best guess at the scenario (please correct me if I am wrong)

  1. Make an AJAX call to get a list of items from a SharePoint custom list, but alas, one of the columns in this list has an InitatorID instead of a user name.
  2. To fix this, we want to make another AJAX call that will get a list of usernames for a matching set of InitatorIDs we just retrieved.
  3. Once we have that, we want to put the data in a dataTable for display.

Without knowing the details, I would just do nested AJAX calls. Basically, once the first call is done, call the second AJAX function. Once that one is done, update the dataTable. Something like:

$.ajax({ 
    url: MY_FIRST_URL,
    data: myFirstData
}).done(function (data) {
    // The first call gets completed after some time and the 'done' function is called.
    // here, extract the various InitatorID values, and pass them to the
    // second AJAX call, so you can then get the usernames for those Ids

    var initatorIds = // ... do data massaging here to get the initatorIds 
                      // into the format you want from the 'data' variable
                     //  passed in the done function...

    $.ajax({ 
        url: MY_SECOND_URL,
        data: initatorIds 
    }).done(function (data2) {
        // once the SECOND call is complete, populate the dataTables

        var jsonData =  // ... some manipulation of data and data2 results
                        // to get the combined output you want. 

        $("#resultsDivMyOutstandingItems").dataTable( {
              "data" : jsonData,
               columns: [
               ....
               ....
        }); 
    }).fail(function (jqXHR, textStatus) {
        // do stuff if the second call fails
    }); 
}).fail(function (jqXHR, textStatus) {
   // do stuff if the first call fails
});

And at the risk of over-complicating the solution, I'd personally look to load the data directly into the table via the ajax functionality found within the dataTable plugin (read more about that here). But definitely if it minimizes confusion to lay it out as above, do that first!