Background: I have a function that takes an array of local link strings, loads each link and finds all of the <a>
tags from a specific location in each link, then pushes each tag's href
attribute into an array called results
.
The Problem: The results array is empty after the function has finished running. If I test the array's length or content with console.log
inside of the .load()
function, the array has content, as I would expect; outside of that function however, the array is empty.
Hypothesis: I think that the populated array is somehow getting overwritten by the empty array, but I can't see how that is happening. I even tried placing the result array outside of the main function, as a global variable, but still it is empty after the function has executed.
Function
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 Call
function ctRunAll(){
createTable("#ctSection h1", 16);
var sectionLinks = collectLinks(hikingContent);
collectAllTrailLinks(sectionLinks[0]);
}
That's because the callback function passed to $("#placeHolder").load()
is executed asynchronously. Which means that function collectAllTrailLinks()
is already finished before the first call to that callback is taking place.
What you can do is return a promise so you can wait until all loads are finished. I've created a code snippet that demonstrates the native Promise way (simplified with setTimeout
instead of $.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 Deferred way
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);
});
Native Promise way
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);
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.