Во-первых, я бы сказал, что нет «оптимального способа», поскольку все они ведут себя несколько по-разному... Во-вторых, я бы добавил, что это не столько специфичная вещь для SharePoint или executeQueryAsync, сколько вещь JS в целом...
Далее нам нужно понять, что executeQueryAsync
ожидает две функции в качестве аргументов: первая — это функция, которая выполняется, если executeQueryAsync
завершается успешно, вторая — это функция, которая выполняется, если метод обнаруживает ошибку. Этим функциям передаются параметры (из executeQueryAsync
, а не из вашего JS), представляющие объект-отправитель, а также объект аргументов, который может иметь некоторые данные (args.get_message()
и args.get_stackTrace()
являются общими в случае неудачного вызова)
В вашем примере «Вариант 1» executeQueryAsync
даются две анонимные функции, вы не сможете повторно использовать их где-либо, но если поведение простое, этого может быть достаточно.
В Варианте 2 вы используете метод createDelegate
, чтобы дать обратным вызовам успеха и неудачи контекст - это говорит о области видимости в JavaScript; если вам нужно сослаться на переменную, доступную только в функции, которая вызывает executeQueryAsync
, вам нужно будет использовать такой шаблон, чтобы this
в обратном вызове ссылался на функцию, вызвавшую executeQueryAsync
, а не на функцию успеха или отказа, которую вы re now in. Вы можете думать о создании делегата как о вызывающей функции, вызывающей какую-то другую функцию, но говорящей: «Я хочу, чтобы эта функция могла видеть то, что вижу я, независимо от того, где она находится в коде». Все это может показаться немного загадочным, но такова область видимости в JavaScript... Вы можете полностью обойти необходимость делать это, ссылаясь на переменные на более высоких уровнях области видимости (скажем, внутри функции, которая содержит вызывающий метод, а также успех и методы отказа)
Вариант 3 аналогичен варианту 2, за исключением того, что он просто указывает, что функции _onSucceed
или _onFail
должны быть теми, которые содержатся в вызывающем объекте.
Вариант 4 аналогичен варианту 1, за исключением того, что вы называете функции (и что они доступны в текущей области) и вызываете их по имени.
Обычно я использую что-то вроде варианта 2 или варианта 4, но я надеюсь, вы понимаете, что на самом деле все зависит от того, как вы пытаетесь структурировать свой код.
РЕДАКТИРОВАТЬ: В ответ на комментарий о Function.createDelagate()
- кажется, это просто помощник в ресурсе сценария ASP.NET; он не делает ничего, кроме вызова apply()
(что является стандартным способом JS для этого -- см. документацию MDN здесь). Это также может обеспечить некоторую обратную совместимость где-то в ASP.NET, но я не совсем уверен!
Вот код функции из файла ресурсов скрипта в моей среде SP:
Function.createDelegate = function(a, b) {
return function() {
return b.apply(a, arguments)
}
};
И в качестве бонуса я подумал о том, как я использую executeQueryAsync
, и я понял, что на самом деле я использую его чаще, как вариант 1, с шаблоном обещания, использующим отложенные jQuery, как это:
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();
}
Затем вы можете делать что-то менее похожее на спагетти, например:
...
ctx.load(items);
getSPDataAsync(ctx).then(function() {
//do some stuff with the data when the promise resolves
});
На всякий случай, если это кого-то волнует! :)
person
John-M
schedule
21.07.2014