Update User On Long Process Progress

I have the need to perform some long database calculations triggered by a user action (an ajax button) in a view:

<?php

$this->widget(‘bootstrap.widgets.TbButton’, array(

'buttonType'=&gt;'ajaxButton',


'ajaxOptions'=&gt;array('update'=&gt;'#status'),


'label'=&gt;'Calculate',


'type'=&gt;'primary', 


'size'=&gt;'small', 


'url'=&gt;array('report/Calculate'),

));

?>

<div id="status"></div>

The calculations done via an action in a controller and are split in a number of function calls:

public function actionCalculate()

    {


        function_1();


        function_2();


        // .....


        // 30+ functions more


        return true


    }

At the moment each function echoes a message when it’s finished but of course the messages are all shown together only at the end of the last function.

I would like to display each message to the user as soon as each function has terminated (or to update a progress bar?).

I have searched for hours on end but I haven’t been able to find an example that suited me, can anyone help?

Thanks a lot!

I guess you need to prevent output buffering or explicitly flush the buffer each time you output an update.

This stack overflow post might get you moving in the right direction.

Thanks Keith, but I have tried that with no success. I guess the problem is that the ajax request only updates the screen when it’s completed.

I have tried to launch individual ajax requests for individual functions but I do now how to make an ajax request without a user action (button, link or else).

To clarify, is there a way to have a button that launches a sequence of sync ajax requests?

R

The easiest way is to call the next URL after each successfully returns.

You could have something like the following (with better function names):




<script type="text/javascript">

    function fn1(data)

    {

        // Update progress here


        // Next request

        $.get("/your/second/url", { your: "params" }, fn2, "json");

    }


    function fn2(data)

    {

        // Update progress here


        // Next request

        $.get("/your/third/url", { your: "params" }, fn3, "json");

    }


    function fn3(data)

    {

        // etc

    }


    $(document).ready(function(){

        $("#your-button").on("click", function(){

            $.get("/your/first/url", { your: "params" }, fn1, "json");

        });

    });

</script>



Each success callback function invokes the next request.

Note that in reality you’d also need to capture any errors and notify the user / clean up.

You could avoid having 20+ nested function calls by using setTimeout(…, 0).

EDIT:

Out of interest, what are the calculations that are taking so long?