1

I know this has been asked before here and I've viewed several similar questions, but I'm just not getting it and could use some assistance. I'm currently reading a file in SharePoint's library via an ajax query that is executed in clientContext.executeQueryAsync(), pretty much exactly as described in SharePoint's documentation:

$(document).ready(function(){

    console.log("Javascript working");

    $("#submit").click(function() {
        file = readFile("/FileName.xlsx/Model/Tables('Table1')?$format=atom");
        console.log(file);
    });
});

function readFile(fileLocation) {
    var clientContext;
    var oWebsite;
    var fileUrl;

    clientContext = new SP.ClientContext.get_current();
    oWebsite = clientContext.get_web();

    clientContext.load(oWebsite);
    clientContext.executeQueryAsync(function () {
        fileUrl = "http://sharepoint2.bankofamerica.com/sites/HadoopAsAServicePortal/PlatformGovernance/_vti_bin/ExcelRest.aspx/Internal%20Team" + fileLocation;

        $.ajax({
            url: fileUrl,
            type: "GET"
        })
            .done(Function.createDelegate(this, successHandler))
            .fail(Function.createDelegate(this, errorHandler));
    }, errorHandler);
}

function successHandler(data) {
    // jsonData = xmlToJson(data.documentElement);
    // cells = serialize(jsonData);
    // pushCellsToLists(cells);
}

The problem is that, when I return the results of a successful query and print them, the result is undefined. I know this is because the query is being executed asynchronously while the console.log is not, and so the value isn't set when the console.log occurs. I also have heard that adding a callback is the solution here, but I'm not that familiar with callbacks and my attempts to implement that solution here have been unsuccessful. Can anyone offer any guidance?

  • I'm not seeing any console logs in the sample code you provide, so it is hard to know where you are seeing that. Also you are combining SP executeQueryAsync with jQuery deferred. I think there is something missing in all this. Why are you doing the executeQueryAsync at all? – Rothrock Nov 7 at 19:29
  • 1
    I've updated the sample code to include where the function is being called and the successHandler (currently empty because I'm not sure what to do with it). As you can now see, the console.log (and also where I need to be able to access the returned data) is outside of the readFile() function, where it is being called. – user87293 Nov 7 at 19:39
  • Yes @Rothrock is right, you are combining two things that you don't need to combine: an async query using executeQueryAsync and another async query using $.ajax. In fact, the way you have it set up is with the $ajax function as the success handler of executeQueryAsync, so if executeQueryAsync succeeds, you don't do anything with what is returned from the server, instead you kick off a second async call using $.ajax. – Dylan Cristy Nov 7 at 19:57
  • 1
    The reason executeQueryAsync is there is because this was copied directly from SharePoint's documentation for how to read a file through Excel Rest: docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/…. Of course, one of the issues I've been dealing with is shoddy documentation :P – user87293 Nov 7 at 20:18
0

I haven't used the _vti_bin/ExcelRest.aspx endpoint, so I'm not quite clear on all the aspects of your issue, but this is how I would structure it.

$(document).ready(function(){
   $("#submit").click(function() {
       console.log("this happens first");

       var file = readFile("/FileName.xlsx/Model/Tables('Table1')?$format=atom")
            .done(function(data){
                console.log("this happens last");
                console.log("File should be in this data somewhere.");
            });

        console.log(file);
        console.log("^^^ that will be a jQuery deferred object because the actual contents aren't back yet.")
    });
});

function readFile(fileLocation){

    var fileUrl = site+"/_vti_bin/ExcelRest.aspx/Internal%20Team" + fileLocation;

    return $.ajax({
        url:fileUrl,
        type:"GET"
        // you may need headers
        // you may need authorization
    })
    .then(function(data){
        // you could preprocess or something with the data in here
        console.log("this happens second");

        // if you have actual data don't return it by itself
        // obj, strings, boolean, etc. are "thenable" wrap with $.when()
        return $.when(data);
    })
    .fail(function(data){
        console.log("Error: REST failed");
        console.log(data);
    });
}

I don't see what your are doing with the SP execute query so I suggest you get rid of that.

Then the important thing with jQuery deferred is that at each point you return a thenable deferred object. Notice when I call $.ajax() that I return that call. This allows the chain to continue.

And at each step in the .then() or .done() I return a thenable object.

  • This did the trick. Thank you! – user87293 Nov 7 at 20:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.