我在SharePoint中的应用中使用以下网站获取所有子网站:
var getW = getWebs($q)
.then(function (results) {
console.log(results); // Object with results from the first execute.
});
function getWebs($q) {
var deferred = $q.defer();
//App context etc..
web = appContextSite.get_web();
subWebs = web.getSubwebsForCurrentUser(null);
context.load(subWebs, 'Include(Url, Created, Title, Lists)');
context.executeQueryAsync(Function.createDelegate(this, function () {
enumSubWebs = subWebs.getEnumerator();
var arraySubWebs = [];
var list = [];
while (enumSubWebs.moveNext()) {
var subWeb = enumSubWebs.get_current(),
subWebUrl = subWeb.get_url();
var _list = subWeb.get_lists().getByTitle('Custom List');
list.push({
'listItem': _list.getItemById(1),
'webTitle': subWeb.get_title()
});
context.load(list[list.length - 1].listItem);
promises.push(list);
}
context.executeQueryAsync(Function.createDelegate(this, function () {
for (var i = 0; i < list.length; i++) {
console.log(list[i].listItem.get_fieldValue()['Title']);
}
// Not sure what to put here, because the promise is returned to my .then above before it enters here.
}));
Q.allSettled(promises).then(function () {
deferred.resolve(list);
});
}));
return deferred.promise;
};
然后,我想从每个网站按ID(在&#39;自定义列表&#39;)中获取一个列表项。
我不知道我做错了什么,但是返回了网页(包括列表数组),但是listItem似乎没有被执行。我应该如何使用promise在最后一次executeQuery之后返回所有内容?
答案 0 :(得分:1)
您正在使用deferred antipattern。每个表示结果的异步操作should get its own promise,只有这样才能正确组合它们。目前你有类似对象列表的数组,但它需要成为一组承诺才能与Q.allSettled
一起使用。
实际上,您甚至不需要Q.allSettled
,因为您不会同时触发多个查询,但只需要一个查询。
让build a helper function for the promise创作:
function load(context, objs, args) {
if (!Array.isArray(objs))
context.load(objs, args);
else
for (var i=0; i<objs.length; i++)
context.load(objs[i], args[i]);
var deferred = $q.defer();
context.executeQueryAsync(function(sender, args) {
deferred.resolve(objs); // sender, args don't seem to be helpful
}, function(sender, args) {
deferred.reject(args);
});
return deferred.promise;
}
现在您可以像这样使用它:
function getWebs($q) {
//App context etc..
var web = appContextSite.get_web();
var subWebs = web.getSubwebsForCurrentUser(null);
return load(context, subWebs, 'Include(Url, Created, Title, Lists)')
// ^^^^^^
.then(function(loadedSubWebs) {
var enumSubWebs = loadedSubWebs.getEnumerator();
var list = [],
loadList = [];
while (enumSubWebs.moveNext()) {
var subWeb = enumSubWebs.get_current(),
subWebUrl = subWeb.get_url();
var obj = {
listItem: subWeb.get_lists().getByTitle('Custom List').getItemById(1),
webTitle: subWeb.get_title()
};
list.push(obj);
loadList.push(obj.listItem);
}
return load(context, loadList).then(function(loadedList) {
// ^^^^^^
for (var i = 0; i < loadedList.length; i++) {
console.log(loadedList[i].get_fieldValue().Title);
}
return list;
});
}, function(err) {
// the load failed. `err` will be the `args` passed to `reject`
console.log("list doesn't exist in this web");
// you can still resolve the promise:
return [];
// or alternatively rethrow the exception:
throw err;
});
}
答案 1 :(得分:0)
这里的内容与Bergi的答案非常相似,但却是独立派生的。
主要区别在于我已将context.load()
语句留在主例程中,并且只是context.executeQueryAsync()
。这比Bergi的load()
更不合理,但是更简单的帮助和更简单的主程序。
var getW = getWebs($q).then(function (results) {
console.log(results); // log the `list` derived from the first execute.
});
function executeQueryPromisified(context) {
/* Ref 1 */
var deferred = $q.defer();
context.executeQueryAsync(
function(sender, args) {
deferred.resolve(args);
},
function(sender, args) {
deferred.reject(args);
}
);
return deferred.promise;
};
function getWebs($q) {
var web = appContextSite.get_web(),
subWebs = web.getSubwebsForCurrentUser(null);
context.load(subWebs, 'Include(Url, Created, Title, Lists)');
return executeQueryPromisified(context).then(function(args) {
var enumSubWebs = subWebs.getEnumerator(),
list = [], subWeb, obj;
while (enumSubWebs.moveNext()) {
subWeb = enumSubWebs.get_current();
obj = {
'listItem': subWeb.get_lists().getByTitle('Custom List').getItemById(1),
'webTitle': subWeb.get_title()
};
list.push(obj);
context.load(obj.listItem);
}
return executeQueryPromisified(context).then(function() {
for (var i = 0; i < list.length; i++) {
console.log(list[i].listItem.get_fieldValue()['Title']);
}
return list;
});
}).catch(function (args) {
/* Ref 1 */
console.error('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
});
};
参考1:Sharepoint documentation; SP.ClientContext.executeQueryAsync method