javascriptrandomwhile-loopinfinite-loop

Why am I unable to draw a random element of an array populated by AJAX?


This on e is a doozey.

I have while loop to generate a random number that is not the same as any other random number produced before. The random number is used to select a text value from an object.

for example:

quoteArray[1] = "some text"
quoteArray[2] = "some different text"
quoteArray[3] = "text again"
quoteArray[4] = "completely different text"
quoteArray[5] = "ham sandwich"

This is part of a larger function and after that function has cycled through = quoteArray.length it resets and starts the cycle over again. The issue I am hitting is that the following code is SOMETIMES producing an infinite loop:

//Note: at this point in the function I have generated a random number once already and stored it in 'randomnumber'
//I use this while statement to evaluate 'randomnumber' until the condition of it NOT being a number that has already been used and NOT being the last number is met.
while(randomnumber === rotationArray[randomnumber] || randomnumber === lastnumber){
    randomnumber = Math.floor(Math.random() * (quoteArray.length));
}

When I console.log(randomnumber) - when I am stuck in the loop - I am just getting '0' as a result. When stuck in the loop it doesn't appear as though Math.floor(Math.random() * (quoteArray.length)) is producing a random number but rather just '0' infinitely.

can anyone tell me why I am running into this problem?



EDIT: Here is the complete pertinent code with function + variable declarations


// Function to initialize the quoteObj
    function quoteObj(text,cname,ccompany,url,height) {
            this.text=text;
            this.cname=cname;
            this.ccompany=ccompany;
            this.url=url;
            this.height=height;
        }

// Populate my quotes Object with the quotation information from the XML sheet. 

    var qObj = new quoteObj('','','','');
    var quoteArray = new Array();
    var counter = 0;

//cycles through each XML item and loads the data into an object which is then stored in an array
    $.ajax({
        type: "GET",
        url: "quotes.xml",
        dataType: "xml",
        success: function(xml) {
            $(xml).find('quote').each(function(){
                quoteArray[counter] = new quoteObj('','','','');
                console.log(quoteArray[counter]);
                quoteArray[counter].text = $(this).find('text').text();
                quoteArray[counter].cname = $(this).find('customer_name').text();
                quoteArray[counter].ccompany = $(this).find('customer_company').text();
                quoteArray[counter].url = $(this).find('project').text();
                ++counter;
            });
        }
    });

// This is the setion that is generating my infinite loop issue.
// I've included all of the other code in case people are wondering specific things about how an item was initialized, etc. 

// Generate a random first quote then randomly progress through the entire set and start all over.      

    var randomnumber = Math.floor(Math.random() * (quoteArray.length));
    var rotationArray = new Array(quoteArray.length);
    var v = 0;
    var lastnumber = -1;

    bHeight = $('#rightbox').height() + 50;
    var cHeight = 0;
    var divtoanim = $('#customerquotes').parent();

//NOT RELATED// 
// Give the innershadow a height so that overflow hidden works with the quotations. 
    $(divtoanim).css({'height' : bHeight});

// Rotate the Quotations Randomly function. 
    setInterval(function(){     
        randomnumber = Math.floor(Math.random() * (quoteArray.length));

//checks to see if the function loop needs to start at the beginning. 
        if(v == (quoteArray.length)){
            rotationArray.length = 0;
            v = 0;
        }
//determines if the random number is both different than any other random number generated before and that is is not the same as the last random number
        while(randomnumber === rotationArray[randomnumber] || randomnumber === lastnumber){
            randomnumber = Math.floor(Math.random() * (quoteArray.length));
        }   

        lastnumber = randomnumber;
        rotationArray[randomnumber] = randomnumber;
        ++v;

//NOT RELATED//
//animation sequence
        $('#ctext, #cname').animate({'opacity':'0'},2000, function(){
            $('#ctext').html(quoteArray[randomnumber].text);
            $('#cname').html('- ' + quoteArray[randomnumber].cname);

            cHeight = $('#customerquotes').height() + 50;
            adjustHeight(bHeight,cHeight,divtoanim);

            $('#ctext').delay(500).animate({'opacity':'1'},500);
            $('#cname').delay(1500).animate({'opacity':'1'},500);
        });
    },15000); 

Solution

  • This is an asynchronous problem: the array quoteArray is empty when the code runs, because it fires off the ajax request, and moves on. Anything that depends on quoteArray should be inside the success function of $.ajax.

    The array has a length when you type quoteArray.length in the console, only because by that time the Ajax request has completed.