简体   繁体   中英

Array gets overwritten

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM