Skip to content Skip to sidebar Skip to footer

How To Set Callback Order Invocation Same As Target Function Invocation

I have a problem in my project. To describe this issue I have wrote simplified code snippet: function waitFor(fnReady, fnCallback) { var check = function() { if (fnRea

Solution 1:

Try this pattern

var map = "abcdefghi".split("");
var responses = []; // collect responses
$.ajaxSetup({
    beforeSend : function(jqxhr, settings) {
      jqxhr.id = Number(settings.data.split(/id=/)[1]); // add `id` to `request`console.log(settings.data.split(/id=/)[1]);
    }
});
var request = function(id, data) {
    // append `id` to `id` datareturn $.post("/echo/json/", {json:JSON.stringify([data]), id:id})
};

$.each(map, function(k, v) {
    setTimeout(function() {
      request(k + 1, v)
      .done(function(data) {
        // do stuff at each responseconsole.log(data); // note return values
      })
      .always(function(data, textStatus, jqxhr) {
          // do stuff at each response
          responses.push([jqxhr.id, data[0]]);
          // do stuff when all requests completed , results items in `responses`if (responses.length === map.length) {
              responses.sort(); // sort `responses` based on `id`// do stuff with `responses`console.log(responses);
          }
      });
    },1 + Math.random() * 1000) // async
});

jsfiddle http://jsfiddle.net/guest271314/g254bbjg/

Solution 2:

my variant:

var index = 0;
// callback functionfunctiontryMe (param1) { 
    waitFor(function(){return param1 == index}, 
            function(){console.log(param1);
                       index++;
                      }
    )   
} 

// callback executer functioncallbackTester (callback,i) {     
    setTimeout( function(){callback(i);}, 20000 - i*1000); 
} 

// test functionfor(var i=0 ; i<10 ; i++){
    callbackTester ( tryMe,i );
}

functionwaitFor(fnReady, fnCallback) {
    var check = function() {
        if (fnReady()) {
            fnCallback();
        }
        else {
            setTimeout(check, 100);  // wait another 100ms, and try again
        }
    };

    check();
}

http://jsfiddle.net/x061dx75/17/

Solution 3:

I personally would use promises for this, but you've said no promises (not sure why), so here's a generic sequencer algorithm in plain javascript (tested in the jsFiddle linked below):

functionsequence(fn) {
    // initialize sequence data upon first useif (typeof sequence.low === "undefined") {
        sequence.low = sequence.high = 0;
        sequence.results = {};
    }
    // save id in local variable so we can reference it in the closure from the function belowvar id = sequence.high;

    // advance to next sequence number
    ++sequence.high;

    // initialize the result value for this sequence callback
    sequence.results[id] = {fn: fn, args: [], ready: false, context: null};

    returnfunction(/* args */) {
        // save args and context and mark it readyvar args = Array.prototype.slice.call(arguments, 0);
        // get the results object for this callback and save info in itvar thisResult = sequence.results[id];
        thisResult.args = args;
        thisResult.context = this;
        thisResult.ready = true;

        // now process any requests in order that are readyfor (var i = sequence.low; i < sequence.high; i++) {
            var result = sequence.results[i];
            // if this one is ready, process itif (result.ready) {
                // increment counter past this result
                ++sequence.low;
                // remove this stored resultdelete sequence.results[i];
                // process this result
                result.fn.apply(result.context, result.args);
            } else {
                // if this one not ready, then nothing to do yetbreak;
            }
        }
    };
}

// your usage:

google.maps.event.addListener(searchBox, 'bounds_changed', sequence(renderTerminalsOnMapAndFitBounds));
...
$.getJSON('getAllTerminals.json', sequence(renderTerminalsOnMapAndFitBounds));
.....
$.getJSON('getAllTerminalsInsideRectangle.json', sequence(renderTerminalsOnMapAndFitBounds));
...
$.getJSON('getAllTerminalsInsideCircle.json', sequence(renderTerminalsOnMapAndFitBounds));
...
$.getJSON('getBigTerminals.json', sequence(renderTerminalsOnMapAndFitBounds));
........

Working demo: http://jsfiddle.net/jfriend00/aqugm1fs/


Conceptually, what this does is as follows:

  1. Pass a substitute completion handler in place of the normal completion callback.
  2. This substitute function marks each response with a sequence id and saved the original completion handler.
  3. If a response comes back while another response with a lower sequence id is still pending, then the result is just stored and saved for later.
  4. As each response comes in, it processes as many responses in sequence as are ready

Note: while all the examples you have use the same callback function, this will work with any callback function so it would work with a mix of different types of operations.

Post a Comment for "How To Set Callback Order Invocation Same As Target Function Invocation"