0
    function loadGraphInSeq(startDate,endDate,calcSubStart,calcSubEnd){
        var graphName=new Array();
        $('section div.graph_box').each(function(){
            if ($(this).css('display')=='block') {
                graphName.push($(this).attr('id'));
            }
        });
        for (index=0;index<graphName.length;index++) {
            switch (graphName[index]) {
                case 'allquery':
                    break;
                case 'alwazinc':
                    alwayzincreasing(calcSubStart,calcSubEnd,startDate,endDate);
                    break;
                case 'segment':
                    ajaxCallingSegment(startDate,endDate,calcSubStart,calcSubEnd);
                    break;
                case 'answeredresponse':
                   ajaxCallingSegmentRespDay(startDate,endDate,calcSubStart,calcSubEnd);
                    break;
                case 'segmentresponse':
                   ajaxCallingSegmentRespHours(startDate,endDate,calcSubStart,calcSubEnd);
                    break;
                case 'lessthanDonut':
                    ajaxCallinglessthanDonut(startDate,endDate,calcSubStart,calcSubEnd,'total');
                    ajaxCallinglessthanDonut(startDate,endDate,calcSubStart,calcSubEnd,'latency');
                    ajaxCallinglessthanDonut(startDate,endDate,calcSubStart,calcSubEnd,'delivery');
                    break;
                case 'carrierPie':
                    ajaxCallingCarrierPie(startDate,endDate,calcSubStart,calcSubEnd);
                    break;
            }

        }
    }

Let me explain a bit, I have class .graph_box which shows graphs. the order of those divs changes when I change the date loadGraphInSeq is called and I want to load the graph in sequence i.e until and unless one graph is loaded other function should not be called. The function in switch statements call the function to load the graphs. Currently this function load all the function in one go. The graphName stacks all the graphs(who are not hidden) name that need to be loaded.

Abhishek Patidar
  • 1,557
  • 1
  • 16
  • 25
  • Calling ajax functions in for loop won't quarantee you sequence of execution. I think you need to call first function from array (pop array), provide callback function for ajaxRequest and then in callback pop array again and call next function. This way you can ensure required sequence. – Yevgeniy.Chernobrivets Nov 20 '13 at 06:52
  • Yeah I got the idea to use callback() function but I don't know how to. I used foreach function but that did not help. Can you show me example. – Abhishek Patidar Nov 20 '13 at 06:55
  • try this link may help you http://stackoverflow.com/questions/19572306/wait-until-all-jquery-ajax-request-are-done-part-2 – vijaykumar Nov 20 '13 at 06:57
  • @Yevgeniy.Chernobrivets using jQuery promise can guarantee the right sequence. I'll post an answer soon. Haven't used jQuery's implementation of promise yet and hear it isn't "standard" so have to check out documentation first (when I have time) – HMR Nov 20 '13 at 07:37
  • Tried with "async: false"? – Murali Mopuru Nov 20 '13 at 08:03
  • @Murali That would be a dumb idea. Especially since there are multiple requests it would lock up the browser until they're all done. – HMR Nov 20 '13 at 08:14
  • I agree that. my suggestion is applicable only if Abhishesk need set of ajax calls in **for loop** with sync behaviour (for whatever need) and you should be ready face implications. Callbacks/queue is the right idea for this. – Murali Mopuru Nov 20 '13 at 08:57
  • @Murali if Abhishesk need set of ajax calls in for loop That doesn't make a need for synch request. Even with callbacks this would be possible but code would be difficult to write. Using promise makes it a lot easier so it's good that jQuery $.get returns a promise. Non asynch methods can create a deferred object with jQuery.Deferred(), resolve it and return a resolved promise with deferred.promise(). http://danieldemmel.me/blog/2013/03/22/an-introduction-to-jquery-deferred-slash-promise/ – HMR Nov 21 '13 at 10:52

2 Answers2

0

You can use the deferred object that $.get returns (or any other XHR method of jQuery).

Using your code I've updated the example. The asynch and synch functions should all return a promise. The asynch (XHR requests) will automatically resolve or fail the synch you do it manually (included in the example)

//your synchronous function
function alwayzincreasing(calcSubStart,calcSubEnd,startDate,endDate){
  var deferred = $.Deferred();  
  deferred.resolve("to be passed to the next function");
  //do stuff here (non asynch);
  //return a promise
  return deferred.promise();
};
function ajaxCallingSegment(startDate,endDate,calcSubStart,calcSubEnd){
  //make sure you return the return value of $.ajax or $.get or $.post
  return $.get("url");//do not put unsuccess or anthing like that here
}
function loadGraphInSeq(startDate,endDate,calcSubStart,calcSubEnd){
  var graphName=new Array(),fn=[],i=-1,len,p,d,e;
  $('section div.graph_box').each(function(){
    if ($(this).css('display')=='block') {
      graphName.push($(this).attr('id'));
    }
  });
  for (index=0;index<graphName.length;index++) {
    switch (graphName[index]) {
      case 'allquery':
        break;
      case 'alwazinc':
        fn.push(function(){
          return alwayzincreasing(calcSubStart,calcSubEnd,startDate,endDate);
        });
        break;
      case 'segment':
        fn.push(function(){
          return ajaxCallingSegment(startDate,endDate,calcSubStart,calcSubEnd);
        });
        break;
      case 'answeredresponse':
        fn.push(function(){
          return ajaxCallingSegmentRespDay(startDate,endDate,calcSubStart,calcSubEnd);
        });
        break;
      case 'segmentresponse':
        fn.push(function(){
          return ajaxCallingSegmentRespHours(startDate,endDate,calcSubStart,calcSubEnd);
        });
        break;
      case 'lessthanDonut':
        fn.push(function(){
          return ajaxCallinglessthanDonut(startDate,endDate,calcSubStart,calcSubEnd,'total');
        });
        fn.push(function(){
          return ajaxCallinglessthanDonut(startDate,endDate,calcSubStart,calcSubEnd,'latency');
        });
        fn.push(function(){
          return ajaxCallinglessthanDonut(startDate,endDate,calcSubStart,calcSubEnd,'delivery');
        });
        break;
      case 'carrierPie':
        fn.push(function(){
          return ajaxCallingCarrierPie(startDate,endDate,calcSubStart,calcSubEnd);
        });
        break;
    }
  }
  len = fn.length;
  d=jQuery.Deferred();
  p = d.promise();
  while(++i<len){
    p.then(fn[i]);
  }
  p.then(function(){
    console.log("done");
  },
  function(){
    console.log("Failed");
  });
  d.resolve();
}
HMR
  • 37,593
  • 24
  • 91
  • 160
  • @AbhishekPatidar I've updated the example to reflect your situation. there are 2 example functions that show what to return to make sure the promise stacking works. – HMR Nov 21 '13 at 11:47
0

This seems to be a very long way to achieve what I want,I have changed the function loadGraphInSeq to return only function name and I am calling that function loadGraphInSeq after every ajax function to get name of next function to call, I load the function name according to div position using

$('section div.graph_box').each(function(){
                                if ($(this).css('display')=='block') {
                                    graphName.push($(this).attr('id'));
                                }
                            });

where graphName is global and stores the name of divs in sequence. LoadGraphInSeq is then called at every end of ajax functions to call next function call.

function loadGraphInSeq(startDate,endDate,calcSubStart,calcSubEnd,graphNametoCall){
                switch (graphNametoCall) {
                    case 'allquery':
                        return(loadGraphInSeq(startDate,endDate,calcSubStart,calcSubEnd,graphName[graphname++]));
                    case 'ajaxCallingAlwazIncr':
                        ajaxCallingAlwazIncr(calcSubStart,calcSubEnd,startDate,endDate);
                        return(loadGraphInSeq(startDate,endDate,calcSubStart,calcSubEnd,graphName[graphname++]));
                    case 'segment':
                        return 'ajaxCallingSegment';
                    case 'answeredresponse':
                        return 'ajaxCallingSegmentRespDay';
                    case 'segmentresponse':
                        return 'ajaxCallingSegmentRespHours';
                    case 'lessthanDonut':
                        return 'ajaxCallinglessthanDonut';
                    case 'carrierPie':
                        return 'ajaxCallingCarrierPie';
                    default:
                        return 0;
                }
        }

This is the code which I have written after every function

 funcToCall=loadGraphInSeq(startDate,endDate,calcSubStart,calcSubEnd,graphName[graphname++]);
                     if (funcToCall!=0) {
                        var strParam = "startDate,endDate,calcSubStart,calcSubEnd";
                        var funcCall = funcToCall + "(" + strParam + ");";
                        eval(funcCall);
                    }
Abhishek Patidar
  • 1,557
  • 1
  • 16
  • 25
  • 1
    You should not use eval and the good news is that you don't have to. Remove the first var statements and replace the eval statement with:`window[funcToCall](startDate,endDate,calcSubStart,calcSubEnd);` – HMR Nov 21 '13 at 10:09