【发布时间】:2014-05-29 06:34:41
【问题描述】:
我在这个函数中不断收到未定义的错误。它分为 5 个单独的函数,我试图在前一个函数完成后运行每个函数,但使用前一个函数返回的数据。我可以嵌套所有回调,但我宁愿使用 Promise。
var checkedOutReport = function () {
var rootSite = window.location.protocol + "//" + window.location.hostname;
//Create array with each collection site
function getAllSites (){
var d = $q.defer();
var allSites = [];
$().SPServices({
operation: "GetAllSubWebCollection",
completefunc: function (xData,Status){
var result = $(xData.responseXML);
result.find('Web').each(function (){
var self = $(this);
allSites.push({
siteTitle: self.attr('Title'),
siteUrl: self.attr('Url')
})
})
}
})
d.resolve(allSites)
return d.promise;
}
//Get libraries for each siteUrl
function getSiteLibraries (allSites) {
var siteCount = allSites.length;
var listPromise = [];
//Go through each site and find document libraries
for (var i = 0; i < siteCount; i++){
listPromise[i] = $().SPServices({
operation: "GetListCollection",
webURL: allSites[i].siteUrl
})
}
//Promise array contains all lists for each site
//Get libraries for each site
$q.all(listPromise).then(findLibraries(listPromise))
}
function findLibraries (promises){
var d = $q.defer();
var siteCount = promises.length;
var allLibraries = [];
//For each site, find the document libraries
for (var i = 0; i < siteCount; i++){
$(promises[i].responseXML).find("List[ServerTemplate='101']").each(function(){
var self = $(this);
allLibraries.push({
listName = self.attr('Title'),
listId = self.attr('ID'),
siteUrl = allSites[i].siteUrl
})
})
}
console.log(allLibraries);
d.resolve(allLibraries);
return d.promise;
}
//CAML QUERIES
var cQueryOptions = "<QueryOptions><ViewAttributes Scope='RecursiveAll' IncludeRootFolder='True' /></QueryOptions>",
cQueryAllCheckedOutDocuments = '<Query><Where><IsNotNull><FieldRef Name="CheckoutUser" /></IsNotNull></Where></Query>',
cQueryModifiedBySystemAccount = '<Query><Where><Contains><FieldRef Name="Editor" /><Value Type="User">system</Value></Contains></Where></Query>',
cViewFields = "<ViewFields Properties='True' />";
//For each library in site collection, find documents which meet criteria
function searchLibraries (library) {
var libraryCount = library.length;
var itemPromise = [];
for (var i = 0; i < libraryCount; i++){
itemPromise[i] = $().SPServices({
operation: "GetListItems",
webURL: library[i].siteUrl,
listName: library[i].listID,
CAMLViewFields: cViewFields,
CAMLQuery: cQueryAllCheckedOutDocuments
})
}
$q.all(itemPromise).then(parseSearchResult(itemPromise))
}
//Clean up result
function parseSearchResult(result){
var d = $q.defer()
var resultCount = result.length;
var returnedFiles = [];
for(var i = 0; i < resultCount; i++){
$(result[i].responseXML).SPFilterNode("z:row").each(function (){
var self = $(this);
var fileName = self.attr('ows_LinkFilename');
var fileUrl = self.attr('ows_FileDirRef').split("#");
var checkedTo = self.attr('ows_LinkCheckedOutTitle');
var modified = self.attr('ows_Modified');
returnedFiles.push({
fileName: fileName,
fileUrl: fileUrl[1],
checkedTo: checkedTo,
modified: modified
});
})
}
d.resolve(returnedFiles);
return d.promise;
}
getAllSites()
.then(
getSiteLibraries(allSites)
)
.then(
searchLibraries(allLibraries)
);
}
【问题讨论】:
-
$().SPServices()是否返回承诺?getAllSites会让我们相信它不会,而getSiteLibraries和searchLibraries会让我们相信它会。 —— -
分号纪律!
-
是的 SPServices 总是返回一个承诺,但我并不总是使用它。例如,getAllSites 只进行一次网络调用,所以我真的不需要它。但是,searchLibraries 正在通过一个 for 循环进行多个操作,因此我在 $q.all() 中使用了 promise
-
蝙蝠侠,在这种情况下,
$().SPServices似乎有点奇怪,因为它既接受了completefunc回调又返回了一个承诺。您通常会期望其中之一。当然,这两种机制可能揭示不同的数据,甚至会更奇怪,但是如果没有 SPServices 的具体知识,谁也无法分辨。文档是否提供任何见解。此外,进行单个调用本身并不是不使用返回的承诺的原因。 -
它们都返回相同的信息,只是如果我使用 completefunc 回调,在回调中发生的任何事情完成之前,我无法进行异步调用,这会大大降低应用程序的速度。使用 Promise,我可以让所有 Web 调用异步地将 Promise 存储在一个数组中,然后从那里使用它们。不过,我并不是真正的 Promise 专家,但仍在试图弄清楚为什么我在让事情正常工作时遇到问题。
标签: javascript jquery angularjs promise jquery-deferred