javascript 在 SharePoint 中调用“SP.ClientContext.executeQueryAsync”的最佳/首选方式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24870104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 03:29:32  来源:igfitidea点击:

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

javascriptsharepointsharepoint-2013sharepoint-clientobject

提问by Naveen

I have been learning client-side object model and came across the method executeQueryAsync. I found there are quite a few ways to call this method. Some of the one I found were these:

我一直在学习客户端对象模型并遇到了方法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);

Which of this way is the most optimal/preferred one? Also what does the statement Function.createDelegatedo? The documentation for this functionseems to be very cryptic for me.

哪种方式是最佳/首选的方式?声明还有什么作用Function.createDelegate这个函数文档对我来说似乎很神秘。

回答by John-M

First I would say there is no 'optimal way' as these all just behave somewhat differently... Second, I would add this isn't so much a SharePoint or executeQueryAsync specific thing as it is a JS thing in general...

首先,我会说没有“最佳方式”,因为它们的行为都有些不同……其次,我要补充一点,这不是 SharePoint 或 executeQueryAsync 特定的东西,因为它通常是 JS 的东西……

Next we need to understand that executeQueryAsyncexpects two functions as arguments: the first is a function to perform if executeQueryAsyncsucceeds, the second is a function to perform if the method encounters an error. These functions are passed parameters (from executeQueryAsync, not from your JS) representing the sending object as well as an arguments object that can have some data (args.get_message()and args.get_stackTrace()are common in the case of a failed call)

接下来我们需要了解,executeQueryAsync需要两个函数作为参数:第一个是executeQueryAsync成功时执行的函数,第二个是方法遇到错误时执行的函数。这些函数传递的参数(来自executeQueryAsync,而不是来自您的 JS)表示发送对象以及可以包含一些数据的参数对象(args.get_message()并且args.get_stackTrace()在调用失败的情况下很常见)

In your 'Option 1' example, executeQueryAsyncis given two anonymous functions, you won't be able to re-use them anywhere, but if the behavior is simple this may be sufficient.

在您的“选项 1”示例中,executeQueryAsync给出了两个匿名函数,您将无法在任何地方重新使用它们,但如果行为很简单,这可能就足够了。

In Option 2 you use the createDelegatemethod to give the success and failure callbacks a context -- this speaks to scoping within JavaScript; if you need to reference a variable that is only accessible in the function that calls executeQueryAsync, you'll need to use this sort of pattern so that thiswithin the callback references the function that called executeQueryAsyncinstead of the success or failure function that you're now in. You can think of creating a delegate as the calling function calling on some other function, but saying 'I want that function to be able to see what I can see no matter where it's located at within the code.' This may all seem a bit arcane, but such is scoping within JavaScript... You could completely circumvent the need for doing this by referencing variables at higher scope levels (say inside of a function that contains the calling method as well as the success and failure methods)

在选项 2 中,您使用该createDelegate方法为成功和失败回调提供上下文——这与 JavaScript 中的作用域有关;如果您需要引用只能在调用的函数中访问的变量,则executeQueryAsync需要使用这种模式,以便this在回调中引用调用的函数executeQueryAsync而不是您现在所处的成功或失败函数。您可以将创建委托视为调用其他函数的调用函数,但是说'我希望该函数能够看到我可以看到的任何地方它位于代码中。这可能看起来有点神秘,但这就是 JavaScript 中的作用域......您可以通过引用更高作用域级别的变量(例如在包含调用方法以及成功和成功的函数内部)来完全规避这样做的需要故障方法)

Option 3 is just like Option 2, except it just specifies that the _onSucceedor _onFailfunctions should be the ones that are contained within the calling object

选项 3 与选项 2 类似,不同之处在于它只是指定_onSucceedor_onFail函数应该是包含在调用对象中的函数

Option4 is just like Option 1, except that you've named the functions (and that they are available within the current scope) and are calling them by name.

选项 4 与选项 1 类似,不同之处在于您已命名函数(并且它们在当前范围内可用)并按名称调用它们。

I usually use something like option 2, or option 4 -- but I hope you can see that it really just depends on how you're trying to structure your code.

我通常使用选项 2 或选项 4 之类的东西——但我希望您能看到这实际上仅取决于您尝试构建代码的方式。

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

编辑:为了回应关于Function.createDelagate()——它似乎只是 ASP.NET 脚本资源中的一个助手的评论;除了调用apply()(这是执行此操作的标准 JS 方式——请参阅此处的 MDN 文档),它什么都不做。它也可能在 ASP.NET 中的某处提供一些向后兼容性,但我不太确定!

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

这是我的 SP 环境中脚本资源文件中的函数代码:

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

And as a bonus, I was thinking about how I use executeQueryAsyncand I realized that I actually use it more often like option 1, with a promise pattern using jQuery deferreds like this:

作为奖励,我在考虑如何使用它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();
}

Then you can do things a little less-spaghetti-like, such as:

然后你可以做一些不那么像意大利面的事情,比如:

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

Just in case anyone cares! :)

以防万一有人关心!:)

回答by Ponnurajesh

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