Оптимальный / предпочтительный способ вызова ' 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 делать? The документация для этой функции кажется, очень загадочно для меня.

2 ответов


во-первых, я бы сказал, что нет "оптимального способа", поскольку все они просто ведут себя несколько иначе... Во-вторых, я бы добавил, что это не столько SharePoint или executeQueryAsync, сколько JS-вещь в целом...

Далее нам нужно понять, что executeQueryAsync ожидает две функции в качестве аргументов: первая-функция для выполнения if executeQueryAsync успешно, второй является функцией для выполнения, если метод сталкивается с ошибкой. Эти функции передаются параметры (от executeQueryAsync, не из вашего JS), представляющего отправляющий объект, а также объект аргументов, который может иметь некоторые данные (args.get_message() и args.get_stackTrace() общие в случае неудачного вызова)

в вашем примере "Вариант 1",executeQueryAsync даны две анонимные функции, вы не сможете повторно использовать их в любом месте, но если поведение простое этого может быть достаточно.

в Варианте 2 вы используете createDelegate метод, чтобы дать успех и неудачу обратные вызовы контекста - это говорит область действия в JavaScript; если вам нужно ссылаться на переменную, доступную только в функции, которая вызывает executeQueryAsync, вам нужно будет использовать такой шаблон, чтобы this в обратном вызове ссылается на функцию, которая вызвала executeQueryAsync вместо функции успеха или неудачи, в которой вы сейчас находитесь. Вы можете подумать о создании делегата как вызывающей функции, вызывающей какую-либо другую функцию, но говорящей: "я хочу, чтобы эта функция могла видеть то, что я вижу, независимо от того, где она находится в пределах кода."Все это может показаться немного загадочным, но такова область в JavaScript... Вы можете полностью обойти необходимость делать это, ссылаясь на переменные на более высоких уровнях области (скажем, внутри функции, которая содержит вызывающий метод, а также методы успеха и неудачи)

Вариант 3 так же, как вариант 2, за исключением того, что он просто указывает, что _onSucceed или _onFail функции должны быть теми, которые содержатся в вызове объект

Option4-это как вариант 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 deferreds выглядит так:

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

на всякий случай, если кто-то заботится! :)


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>​​​​​