0

I have a CSHTML page where I need to make three separate Ajax calls in order, and each one has to wait until the previous one(s) have returned before running. I want to put a message on the webpage showing which of the calls is being handled at that particular time.

However, using async: false does not work as the second call will start before the first one is completed, and using "async: true" does not work as the page does not update until all three calls are completed, at which point there is no need to display a progress message.

This is what I mean:

function doFullAnalysis() {
    doAnalysisStep(1);
    doAnalysisStep(2);
    doAnalysisStep(3);
    showTheResults();
}

function doAnalysisStep(runType) {
    $(button_div).html("Type " + runType + " processing...");
    $.ajax({
        type: "GET",
        url: '@Url.Action("AnalyzeDataRun", "DataHandler.svc")',
        data: {"RunType": runType},
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (data) {
        },
        error: function (HelpRequest, ErrorCode, TheError) {
            resultString = "Error running the analysis:<br />" + TheError;
            $(item_div).html(resultString);
        },
        async: false;
    });
}

As written, doFullAnalysis will call doAnalysisStep three times, but will not update block button_div until all three calls to doAnalysisStep() and the call to showTheResults() are completed. However, if I remove "async: false", then the second call is done before the first one is completed, which is a Bad Thing as the second call depends on the results of the first one.

I have also tried:

var isRunning = false;

function doFullAnalysis() {
    doAnalysisStep(1);
    while (isRunning);
    doAnalysisStep(2);
    while (isRunning);
    doAnalysisStep(3);
    while (isRunning);
    showTheResults();
}

function doAnalysisStep(runType) {
    $(button_div).html("Type " + runType + " processing...");
    isRunning = true;
    $.ajax({
        type: "GET",
        url: '@Url.Action("AnalyzeDataRun", "DataHandler.svc")',
        data: {"RunType": runType},
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (data) {
        },
        error: function (HelpRequest, ErrorCode, TheError) {
            resultString = "Error running the analysis:<br />" + TheError;
            $(item_div).html(resultString);
        },
        complete: function() {
            isRunning = false;
        }
    });
}

However, this puts it in what appears to be an infinite loop; I think it is too busy handling the first while (isRunning) loop to let isRunning = false in the complete block execute.

Is there a way to handle updating the page between synchronous requests?

  • 2
    The standard way to handle this (without resorting to `async: false` which is almost never a good idea) would be to call the next request in the `success` callback of the previous one. There you could also update your progress bar. – Pekka May 08 '17 at 15:24
  • The reason `async: false` is frowned upon is that it blocks the UI from updating while the async call is occurring. So, yeah, don't do that. See http://stackoverflow.com/q/14806168/215552 for how to do queue multiple asynchronous ajax calls. – Heretic Monkey May 08 '17 at 17:37

1 Answers1

0

Good day. Example of multiple asynchronous jQuery Ajax calls

<!....input data div elements.....>

<progress id="mainProgress" value="0" max="100" style="width:1034px;display:none"></progress>

<script>
function getNode(el){return document.getElementById(el);}

var bigData=[];
var dataIndex=0;

function processBigRequest(url,parameters){
    var text=bigData[dataIndex];
    text=encodeURL(text);   
    $.ajax({                
      url: url,
      type: "POST",
      crossDomain: true,
      dataType: "text",
      data: parameters+text,
      success: function( data ) {
        data=data.replace(/\n/g,"<br/>\n");
        getNode("mainDictReport").innerHTML+=data;
        //alert(dataIndex);
        dataIndex++;
        if(dataIndex<bigData.length){
            getNode("mainProgress").value=dataIndex*100/bigData.length+5;
            processBigRequest(url,parameters);
        }else{  
            getNode("startBtn").src="/work_file/_img/Start.jpg";
            getNode("mainProgress").value=0;
            getNode("mainProgress").style.display="none";
        }   

      }     
    });
}

function processRequest(url,parameters,textData,chinkSize){

    getNode("mainDictReport").innerHTML="";
    textData=encodeURL(textData);               

    if(textData.length>chinkSize){
        getNode("startBtn").src="/edit/images/Preloader_8.gif";
        alert("This file is big, please wait till full text will converted");
        getNode("mainProgress").style.display="block";
        getNode("mainProgress").value=3;
        bigData=[];
        var index=0;
        var nLine=encodeURL('\n');
        lines=textData.split(nLine);
        var text="";
        for(var i=0;i<lines.length;i++){
            text+=lines[i]+"\n";
            if(i>0&&i%chinkSize==0){
    bigData.push(text);
    text="";    
            }
        }
        bigData.push(text);
        text="";
        processBigRequest(url,parameters);
    }else{
       //handle direct request
    }

}
</script>

This loads every chunk of data one-by-one and update progress bar.

Nick
  • 138,499
  • 22
  • 57
  • 95
dharmabook.ru
  • 107
  • 1
  • 6