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() {
Just in case, someone cares! :)