Оптимальный/предпочтительный способ вызова SP.ClientContext.executeQueryAsync в SharePoint

Я изучал объектную модель на стороне клиента и наткнулся на метод executeQueryAsync. Я обнаружил, что есть довольно много способов вызвать этот метод. Некоторые из тех, что я нашел, были такими:

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);

Какой из этих способов является наиболее оптимальным/предпочтительным? И что делает оператор Function.createDelegate? документация по этой функции кажется очень загадочно для меня.


person Naveen    schedule 21.07.2014    source источник


Ответы (2)


Во-первых, я бы сказал, что нет «оптимального способа», поскольку все они ведут себя несколько по-разному... Во-вторых, я бы добавил, что это не столько специфичная вещь для 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
comment
Прекрасное объяснение, Джон. Спасибо! Еще кое-что. Заявление Function.createDelegate похоже из SharePoint, так как я не могу найти для него никакой официальной документации. Я прав? - person Naveen; 22.07.2014
comment
Навин, похоже, это просто помощник из ресурса сценария ASP.NET - я обновил свой ответ, включив в него дополнительную информацию. Function.createDelegate не входит ни в одну нативную реализацию JS. - person John-M; 22.07.2014
comment
Здесь действительно помогает jQuery Deferred. Я делаю то же самое. - person Derek Smith; 24.06.2015

person    schedule
comment
Пожалуйста, отредактируйте свой ответ, добавив некоторые пояснения. Избегайте ответа только на код, взгляните на: stackoverflow.com/help/how-to-answer - person GGO; 09.03.2018