3

I have a long loading for loop inside a function in one of my model in my Joomla component. In order to gauge the progress, I wanted to make a progress bar using ajax and javascript as the request is being processes.

As a start, I made a simple ajax call to a function of one of the controllers which contains the following code:

   $mainframe =JFactory::getSession();
   $i=$mainframe->get('component.progress', 0);
   $echo($i);

Here I'm using getSession, but as far as I have understood, session and userstate or almost the same, except for userstate allowing some other things and saving the variables in the registry. I have tried both, and the results are the same.

The get comes from inside the foor loop of my function inside the model, that does the heavy computation, and lookings something like this:

for ($i = 1; $i < min(600, count($this->dati)); $i++) {
        $mainframe = JFactory::getSession();
        $mainframe->set('component.progress', $i);
        heavy computation...
}

then when running the php script I simply call this javascript function with set_interval that dumps periodically the content of the site showing when invoking the function on to the existing site:

function loadXMLDoc()
{
    var xmlhttp;
    if (window.XMLHttpRequest)
    {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    }
    else
    {// code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.onreadystatechange = function ()
    {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
        {
            document.getElementById("myDiv").innerHTML = xmlhttp.responseText;
        }
    }
    xmlhttp.open("GET", "index.php?option=com_contentimporter&task=contentimporter.test", true);
    xmlhttp.send();
}

So far so good, the problem is that the user state does not get updated when the script runs. It seems like it only gets updated after it is done. Now what I suspect is that joomla puts these values into a buffer that it sets only when a pending request is done.

This is unfortunately no good for what I am trying to do.

Do anyone have any suggestion as to what I could do instead. It would be best if I could do this without modifying any default setting in Joomla.

edit: Ok, I've noticed something new, when the php function is done running, I output some feedback that I get from the userstate which I set at the end of the method in my model that does the heavy calculation. I've noticed that this feedback is displayed correctly, but only sometimes.

That is, some times it displays the feedback from the previous processing, some times it displays the feedback from the current one. Sometimes I can refresh the window after a couple of seconds and the correct feedback will show (everytime I refresh, getUserstate on the feedback is called), other times I have to rerun the script n times before the correct feedback shows.

It seems to behave in an erratic and random way. Maybe I have accidentily deleted some table values or changed some settings in Joomla that could cause this? Does anyone have an idea?

Also, I read that if the registry for some reason was not set (setUserstat will do nothing in this case), I could do:

    $session = JFactory::getSession();
    $registry=$session->get('registry',null);
    if(is_null($registry)) {
        $session->set('registry', new JRegistry('session'));
    }

I have tried this but it does not seem to fix the problem.

Also I should not that I use J!Dump occasionally to display info about some variables, and I also have the exact same problem with this component, the window with the dump pops up only occasionally.

1

Well I believe I had a similar problem once where I got random results. For me, the solution was using a synchronous request (instead of the asynchronous one, which you are using, too, if I am not mistaken). This is somewhat decreasing performance, but will force the request to be executed in an orderly fashion.

I just found this page which explains and gives some examples. Try just changing

 xmlhttp.open("GET", "index.php?option=com_contentimporter&task=contentimporter.test", true);

to

 xmlhttp.open("GET", "index.php?option=com_contentimporter&task=contentimporter.test", false);

The "false" should make the request synchronous.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.