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
    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
    Jul 21, 2015 at 17:33

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .