Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pushing to an Array within a jQuery each loop

I'm using jQuery to parse an XML file, and I'm trying to push each element in the XML file to an array using a jQuery .each loop. Strangely, if I alert the value of the array within the loop it comes out as it should, but if I try to alert a value in the array after the loop has finished it results in "undefined".

Is there something strange that happens when you push values to an array within this kind of a loop?


Here is the Javascript:

var splashArray = new Array();

// Load the Splash XML file and assign each image within to an array
$.get('splash.xml', function(xml) {
    $('image', xml).each(function (i) {
        splashArray.push($(this).attr("src"));
    });
});

alert(splashArray[1]); // Results in undefined



Here is the XML:

<?xml version="1.0" encoding="UTF-8"?>
<site>      
    <image src="splash1.jpg" />
    <image src="splash2.jpg" />
    <image src="splash3.jpg" />
    <image src="splash4.jpg" />
    <image src="splash5.jpg" />
    <image src="splash6.png" />
</site>
like image 734
cmal Avatar asked Sep 27 '09 19:09

cmal


2 Answers

Correct variant:

var splashArray = new Array();

// Load the Splash XML file and assign each image within to an array
$.get('splash.xml', function(xml) {
        $('image', xml).each(function (i) {
                splashArray.push($(this).attr("src"));
        });
        alert(splashArray[1]);
});

In your variant of code alert(splashArray[1]); executes before ajax get xml result, therefore splashArray was empty, when you try to alert element with index 1. Your code works well only for synchronous mode, when thread waits for server response. In Asynchronous mode you should use callback function.

Variant with callback:

var splashArray = new Array();

// Load the Splash XML file and assign each image within to an array
$.get('splash.xml', function(xml) {
        $('image', xml).each(function (i) {
                splashArray.push($(this).attr("src"));
        });
        work_with_splash();
});

function work_with_splash () {
    alert(splashArray[1]);
}

Or one more pattern (pseudocode):

function process(ajax_is_done) {
    if (!ajax_is_done) {
        ajax(function (result) {
            import_result(result);
            process(true);
        })
    }
}
process();
like image 171
Anatoliy Avatar answered Oct 20 '22 02:10

Anatoliy


You are alerting before the array is being populated. You need to understand that XHR/Ajax is asynchronous ( as opposed to synchronous ) so the alert will not always run after the callback function because it will take a few seconds to do the actual HTTP request to grab the xml, alerting inside the callback ensures that it is populated after the XHR stuff is done.

Works:

var splashArray = [];

function fn() {
    alert(splashArray[1]);
}

$.get('splash.xml', function(xml) {
        $('image', xml).each(function (i) {
                splashArray.push($(this).attr("src"));
        });
        fn();
});

Doesn't work:

var splashArray = [];

$.get('splash.xml', function(xml) {
        $('image', xml).each(function (i) {
                splashArray.push($(this).attr("src"));
        });
        // this will populate the array almost always AFTER the alert below.
});


alert(splashArray[1]); // this will almost ALWAYS alert BEFORE the callback function is done
like image 45
meder omuraliev Avatar answered Oct 20 '22 01:10

meder omuraliev