Optimal / preferred way to call "SP.ClientContext.executeQueryAsync" in SharePoint

I am studying the client side object model and came across the executeQueryAsync method. I found that there are many ways to name this method. Some of them I found:

 var context = new SP.ClientContext.get_current(); // Option 1 context.executeQueryAsync( function(sender, args){ }, function(sender, args){ } ); // Option 2 context.executeQueryAsync( Function.createDelegate(this, _onSucceed), Function.createDelegate(this, _onFail) ); // Option 3 context.executeQueryAsync( Function.createDelegate(this, this._onSucceed), Function.createDelegate(this, this._onFail) ); // Option 4 context.executeQueryAsync(_onSucceed, _onFail); 

Which of these methods is the most optimal / preferred? And what does the Function.createDelegate statement do? The documentation for this feature seems very mysterious to me.

+7
javascript sharepoint sharepoint-2013 client-object-model sharepoint-clientobject
source share
2 answers

First, I would say that there is no β€œoptimal way”, since all this behaves differently. Secondly, I would add that this is not so much a specific SharePoint thing, or execQueryAsync, since it is generally a JS thing ...

Next, we need to understand that executeQueryAsync expects two functions as arguments: the first is the function executed if executeQueryAsync succeeds, the second is the function executed if the method encounters an error. These functions are passed by parameters (from executeQueryAsync , not from your JS) representing the dispatch object, as well as an argument object that may have some data ( args.get_message() and args.get_stackTrace() are common in case of an unsuccessful call)

In your β€œOption 1” example, executeQueryAsync two anonymous functions defined, you cannot reuse them anywhere, but if the behavior is simple, that may be enough.

In Option 2, you use the createDelegate method to give success and refusal to call the context - this suggests that JavaScript uses JavaScript; if you need to refer to a variable that is available only in the function that calls executeQueryAsync , you will need to use this type of template so that this in the callback refers to a function called executeQueryAsync instead of success or the failure function that you are currently in. You can think of creating a delegate as a calling function that calls some other function, but saying: "I want this function to see what I see, regardless of where it is inside the code. ' This may seem a little cryptic, but it is in the JavaScript realm, you can completely circumvent this need by referring to variables at higher levels of coverage (say, inside a function that contains the calling method, as well as success and failure methods)

Option 3 is similar to option 2, except that it simply indicates that the _onSucceed or _onFail should be those contained in the calling object

Option 4 is similar to option 1, except that you named the functions (and that they are available in the current area) and call them by name.

I usually use something like option 2 or option 4, but I hope you see that it really depends on how you try to structure your code.

EDIT: In response to a comment about Function.createDelagate() - it seems to be just a helper in an ASP.NET script resource; it does nothing but call apply() (which is the standard JS way to do this - see the MDN documentation here ). It may also provide some backward compatibility somewhere inside ASP.NET, but I'm not sure!

Here is the code for the function from the script resource file in my SP environment:

 Function.createDelegate = function(a, b) { return function() { return b.apply(a, arguments) } }; 

And as a bonus, I was thinking about how I use executeQueryAsync , and I realized that I use it more often, as option 1, with a promise template using deferred jQuery as follows:

 function getSPDataAsync(context) { var deferred = $.Deferred(); context.executeQueryAsync(function(sender, args) { deferred.resolve(sender, args); }, function(sender, args) { deferred.reject(sender, args); }); return deferred.promise(); } 

Then you can do something a little less-spaghetti, for example:

 ... ctx.load(items); getSPDataAsync(ctx).then(function() { //do some stuff with the data when the promise resolves }); 

Just in case, someone cares! :)

+13
source share
 Please try the below answer...this should help..Below code uses the context.ExecutequeryAsync method but since the items are captured separately on a string array there should not be any issues with respect to asynchronous behavior.. <style> table { table-layout: fixed; } td { width: 50%; } </style><script type="text/javascript"> function ShowselectedItems() { var ctx = new SP.ClientContext.get_current(); web = ctx.get_web(); if (ctx != undefined && ctx != null) { var listId = SP.ListOperation.Selection.getSelectedList(); var oList = ctx.get_web().get_lists().getByTitle('Testform'); // Put your list name here var selectedItems = SP.ListOperation.Selection.getSelectedItems(ctx); var camlquerystr = ''; if(selectedItems.length > 0){ if(selectedItems.length == 1) { camlquerystr += '<Where><Eq><FieldRef Name=\'ID\'/><Value Type=\'Number\'>' + selectedItems [0].id + '</Value></Eq></Where>'; } else if(selectedItems.length == 2) { camlquerystr += '<Where><Or><Eq><FieldRef Name=\'ID\'/><Value Type=\'Number\'>' + selectedItems [0].id + '</Value></Eq><Eq><FieldRef Name=\'ID\'/><Value Type=\'Number\'>' + selectedItems[1].id + '</Value></Eq></Or></Where>'; } else { var i; camlquerystr += '<Where>'; for (i = 0; i < selectedItems.length - 1; i++) { camlquerystr += '<Or><Eq><FieldRef Name=\'ID\'/><Value Type=\'Number\'>' + selectedItems [i].id + '</Value></Eq>'; } camlquerystr += '<Eq><FieldRef Name=\'ID\'/><Value Type=\'Number\'>' + selectedItems[i].id + '</Value></Eq>'; for (i = 0; i < selectedItems.length - 1; i++) { camlquerystr += '</Or>'; } camlquerystr += '</Where>'; } } else { alert('Please select your item'); retrun; } var camlQuery = new SP.CamlQuery(); camlQuery.set_viewXml('<View><Query>' + camlquerystr + '</Query></View>'); this.collListItem = oList.getItems(camlQuery); ctx.load(collListItem, 'Include(Id, Title,Name,First_x0020_Name,Last_x0020_Name)'); ctx.executeQueryAsync(Function.createDelegate(this, this.success), Function.createDelegate(this, this.failed)); } } function success() { var listItemInfo = ''; var headstr = "<html><head><title></title></head><body>"; var footstr = "</body>"; var content; var listItemEnumerator = collListItem.getEnumerator(); while (listItemEnumerator.moveNext()) { var oListItem = listItemEnumerator.get_current(); content += "<table border='1' width='100%' style='table-layout: fixed;'><tr><td>Title:</td><td>" + oListItem.get_item('Title') + "</td></tr><tr><td>Name:</td><td>" + oListItem.get_item('Name') + "</td></tr><tr><td>First Name:</td><td>" + oListItem.get_item('First_x0020_Name') + "</td></tr><tr><td>LastName:</td><td>" + oListItem.get_item('Last_x0020_Name') + "</td></tr></table><br/><br/>"; } w = window.open("", "_blank", "k"); w.document.write(headstr + content + footstr); w.print(); } function failed(sender, args) { alert('failed. Message:' + args.get_message()); } </script><a href="#" onclick="javascript:ShowselectedItems();">Show Items</a>​​​​​ 
-2
source share

All Articles