在第二次调用geteneration时,集合还没有初始化

The collection has not been initialized on SECOND call of getEnumeration

本文关键字:集合 还没有 初始化 第二次 调用 geteneration      更新时间:2023-09-26

我尝试在SharePoint中接收一个用户的子网页。在第一次调用接收子网站时(函数getSubWebs()),一切正常:子网站被接收,我可以遍历它们。

然而,我尝试使用相同类型的代码获得这些网站的子网站var webSubEnumerator = subwebcollection . getenenumerator ();抛出错误
The collection has not been initialized

尽管我之前使用了Load(),并且在ExecuteQueryAsync的"success"部分(就像在web父请求上一样)。

是什么导致这里的问题?

var context = SP.ClientContext.get_current();
var user = context.get_web().get_currentUser();
var web = context.get_web();
var lists = web.get_lists();
var parrentwebCollection = null;
ExecuteOrDelayUntilScriptLoaded(getSubWebs, "sp.js"); 
function getSubWebs(){
  parrentwebCollection = web.getSubwebsForCurrentUser(null);
  context.load(parrentwebCollection)
  context.executeQueryAsync(onGetSubwebsSuccess, onGetSubwebsFail);
}
function onGetSubwebsSuccess(sender, args){
  var webEnumerator = parrentwebCollection.getEnumerator();
  // Everything works FINE on this getEnumerator()
  while (webEnumerator.moveNext()){
    var webParrent = webEnumerator.get_current();
    var parrenttitel = webParrent.get_title();
    var parrenturl = webParrent.get_url();
    //Load Subs From Parrent
    var subwebCollection = null;
    subwebCollection = webParrent.getSubwebsForCurrentUser(null);
    if (subwebCollection != undefined && subwebCollection != null) { 
      context.load(subwebCollection);
      context.executeQueryAsync(onGetSSubwebsSuccess, onGetSSubwebsFail);
      function onGetSSubwebsSuccess(sender, args) {
        console.log("getSubWebs query successful")
        var webSubEnumerator = subwebCollection.getEnumerator();
        // THIS getEnumerator(), however throws an exception
        while (webSubEnumerator.moveNext()){
          console.log("After While")
          var subweb = webSubEnumerator.get_current();
          var subtitel = subweb.get_title();
        }              
      }
      function onGetSSubwebsFail(sender, args){
        alert("Request to retrieve subwebs failed. Error: " + args.get_message())
      }
    }
  }              
}
function onGetSubwebsFail(sender, args){
  alert("Request to retrieve subwebs failed. Error: " + args.get_message())
}

请注意,我在executeQueryAsync().的Success()-函数内,所以我相信这不是典型的"在它存在之前试图读取异步数据"-问题

出现问题是因为您在while循环中多次调用回调函数,并且回调函数从包含作用域引用一个变量(subwebCollection)——这意味着函数的每次调用都访问包含函数作用域中定义的相同共享变量(因此也是相同的共享值)。

(与大多数编程语言不同,JavaScript是函数作用域,而不是块作用域。)

可以通过在while循环中使用"闭包"来绕过这个问题,以确保回调函数的每次调用都有对其所需变量的本地副本的引用。

function onGetSubwebsSuccess(sender, args) {
    var webEnumerator = parentwebCollection.getEnumerator();
    while (webEnumerator.moveNext()) {
        var webparent = webEnumerator.get_current();
        var parenttitle = webparent.get_title();
        (function(){ /* anonymous function expression wraps the subwebCollection variable in a closure (creates a new scope for the variable) */
            var subwebCollection = null;
            subwebCollection = webparent.getSubwebsForCurrentUser(null);
            if (subwebCollection != undefined && subwebCollection != null) {
                context.load(subwebCollection);
                context.executeQueryAsync(onGetSSubwebsSuccess, onGetSSubwebsFail);
                function onGetSSubwebsSuccess(sender, args) {
                    console.log("getSubWebs query successful")
                    var webSubEnumerator = subwebCollection.getEnumerator();
                    while (webSubEnumerator.moveNext()) {
                        console.log("After While")
                        var subweb = webSubEnumerator.get_current();
                        var subtitel = subweb.get_title();
                    }
                }
                function onGetSSubwebsFail(sender, args) {
                    alert("Request to retrieve subwebs failed. Error: " + args.get_message())
                }
            }
        })(); /* we immediately invoke the function expression */
    }
}

这种技术通常被称为立即调用函数表达式(IIFE)。

(function(){
    // closure
})();

这只不过是一种强制JavaScript模仿块级作用域而不是函数级作用域的方法。