6

I am fairly new to javascript and have spent some time trying to understand callbacks as they relate to SharePoint's CSOM, but have had some issues.

Essentially, I am running a query to get a collection of list items, then for each of those items, requesting additional information in a query from SharePoint. The problem is that I would like to then compile all those individual requests together and essentially "return" them.

I have tried putting the essentials of my script below, any help understanding how to properly issue a callback in this structure would be appreciated:

function mainFunctionHere() {
   ...[pull up a collection of list items]...

   clientContext.load(collListItem);    
   clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed)); 
}

var emailList = '';

function onQuerySucceeded() {
   var listItemEnumerator = collListItem.getEnumerator();
   while (listItemEnumerator.moveNext()) {
      var oListItem = listItemEnumerator.get_current();
      appendUserInfo(oListItem.get_item('Name').get_lookupId(), addToEmailList) + '; ';
   }
   alert(emailList); //this is where I would like to return the full list, but obviously it is executing before any queries in appendUserInfo complete
}

function appendUserInfo(userId)
{
   ...[query siteUserInfoList for email info on the provided user id]...

   context.load(items,'Include(EMail)');
   context.executeQueryAsync(function(){
   if(items.get_count() > 0) {
      var item = items.itemAt(0);
      emailString = item.get_fieldValues().EMail;
   }
   emailList += emailString + "; ";
   alert(emailList);
 }
);
}

1 Answer 1

7

You will need to use $.Deferred() as well as $.when(). Modify appendUserInfo() to be like the following:

function appendUserInfo(userId) {
    var d = $.Deferred();
    context.load(items, 'Include(EMail)');
    context.executeQuerAsync(function(){
        if(items.get_count() > 0) {
            var item = items.itemAt(0);
            emailString = item.get_fieldValues().EMail;
        }
        emailList += emailString + '; ';
        alert(emailList);
        d.resolve();
    });
    return d.promise();    
}

Modify your first success function to be as follows:

function onQuerySucceeded() {    
    var listItemEnumerator = collListItem.getEnumerator();
    var asyncCallbacks = [];
    while (listItemEnumerator.moveNext()) {        
        var oListItem = listItemEnumerator.get_current();
        asyncCallbacks.push(appendUserInfo(oListItem.get_item('Name').get_lookupId(), addToEmailList));        
    }
    $.when.apply($, asyncCallbacks).done(function() {
        alert(emailList);        
    });    
}

This SO answer explains $.when.apply($, array) in far better detail than I could.

Also, not entirely sure what's going on in "...[query siteUserInfoList for email info on the provided user id]...", but perhaps modifying it to take an array instead of a single value would be better.

2
  • Okay, this worked perfectly on the first try. Thanks so much. I had read about promises previously but wasn't sure if they were considered a "less ideal" solution than properly setting up callbacks.
    – user11457
    Commented Jul 21, 2015 at 17:22
  • And yes, you are right about feeding it an array instead of individual items from a loop. I can look into cleaning this up a bit now that I have it working properly.
    – user11457
    Commented Jul 21, 2015 at 17:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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