我尝试在SharePoint中接收用户子网站的子网站。 在第一次接收子网站的调用(函数getSubWebs())一切都很好:接收子网站,我可以遍历它们。
然而,当我尝试使用相同类型的代码获取这些网站的子网站时 var webSubEnumerator = subwebCollection.getEnumerator();抛出错误
The collection has not been initialized
即使我之前使用过Load()并且在ExecuteQueryAsync的“成功”部分内部(就像在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()函数内部所以我相信这不是典型的“尝试在异常数据存在之前读取” - 问题
答案 0 :(得分:1)
问题出现了,因为您在while循环中多次调用回调函数,并且回调函数从包含的范围引用变量(subwebCollection
) - 意味着每次调用function访问包含函数作用域中定义的相同共享变量(以及相同的共享值)。
(与大多数编程语言不同,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模仿块级范围而不是其变量的函数级范围的方法。