后台:我有一个函数,它接受一组本地链接字符串,加载每个链接并从每个链接中的特定位置查找所有<a>
标记,然后推送每个将href
属性标记为名为results
的数组。
问题:函数运行完毕后,结果数组为空。如果我在console.log
函数内部使用.load()
测试数组的长度或内容,则数组具有内容,正如我所期望的那样;但是,在该函数之外,数组是空的。
假设:我认为填充的数组会以某种方式被空数组覆盖,但我无法看到它是如何发生的。我甚至尝试将结果数组放在main函数之外,作为全局变量,但在函数执行后它仍然是空的。
功能
function collectAllTrailLinks(arrayOfSections){
var result = [];
var len = arrayOfSections.length;
$("body").append("<div id='placeHolder'></div>");
for (var i = 0; i < len; i++) {
var params = arrayOfSections[i] + " " + "blockquote a";
$("#placeHolder").load(params, function(){
$("#placeHolder a").each(function(){
var link = $(this).attr("href");
if (link !== "symbols.html") {
result.push(link);
}
});
});
}
console.log(result.length);
//return result;
}
功能调用
function ctRunAll(){
createTable("#ctSection h1", 16);
var sectionLinks = collectLinks(hikingContent);
collectAllTrailLinks(sectionLinks[0]);
}
答案 0 :(得分:4)
那是因为传递给$("#placeHolder").load()
的回调函数是异步执行的。这意味着函数collectAllTrailLinks()
在第一次调用该回调之前已经完成。
您可以做的是返回一个承诺,这样您就可以等到所有负载完成。我创建了一个代码片段,演示了原生的Promise方式(使用setTimeout
而不是$.load
进行了简化)
var output = document.getElementById('output');
function collectAllTrailLinks() {
var promises = [];
for (var i = 0; i < 20; i++) {
var promise = new Promise(function(resolve, reject) {
var index = i;
setTimeout(function() {
output.innerHTML += 'finished ' + index + ' ';
resolve('result of ' + index);
}, i * 200);
});
promises.push(promise);
}
return Promise.all(promises);
}
collectAllTrailLinks().then(function (result) {
output.innerHTML += '<br /><br />All done: ' + JSON.stringify(result);
});
<div id="output"></div>
JQuery延迟方式
function collectAllTrailLinks(arrayOfSections) {
var defer = $.Deferred();
var result = [];
var len = arrayOfSections.length;
var finishedLoads = 0;
$("body").append("<div id='placeHolder'></div>");
for (var i = 0; i < len; i++) {
var params = arrayOfSections[i] + " " + "blockquote a";
$("#placeHolder").load(params, function(){
$("#placeHolder a").each(function(){
var link = $(this).attr("href");
if (link !== "symbols.html") {
result.push(link);
}
});
finishedLoads++;
if (finishedLoads == len) {
defer.done(result); // mark deferred as done (will resolve promise)
}
});
}
return defer.promise(); // return promise where you can wait on
}
// Usage (wait for promise)
collectAllTrailLinks(arrayOfSections).done(function(result) {
console.log(result.length);
});
原生承诺方式
function collectAllTrailLinks(arrayOfSections) {
var promises = [];
$("body").append("<div id='placeHolder'></div>");
for (var i = 0; i < arrayOfSections.length; i++) {
var promise = new Promise(function(resolve, reject) {
var params = arrayOfSections[i] + " " + "blockquote a";
$("#placeHolder").load(params, function(response, status, xhr) {
if (status === "error") {
return reject(response);
}
var result = [];
$("#placeHolder a").each(function() {
var link = $(this).attr("href");
if (link !== "symbols.html") {
result.push(link);
}
});
resolve(result);
});
});
promises.push(promise);
}
return Promise.all(promises);
}
// Usage
collectAllTrailLinks(arrayOfSections).then(function(results) {
console.log(results.length);
});