How to set callback order invocation same as target function invocation

后端 未结 3 2054
谎友^
谎友^ 2021-01-29 10:33

I have a problem in my project.

To describe this issue I have wrote simplified code snippet:

function waitFor(fnReady, fnCallback) {
    var check = fun         


        
3条回答
  •  悲哀的现实
    2021-01-29 10:53

    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):

    function sequence(fn) {
        // initialize sequence data upon first use
        if (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 below
        var 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};
    
        return function(/* args */) {
            // save args and context and mark it ready
            var args = Array.prototype.slice.call(arguments, 0);
            // get the results object for this callback and save info in it
            var thisResult = sequence.results[id];
            thisResult.args = args;
            thisResult.context = this;
            thisResult.ready = true;
    
            // now process any requests in order that are ready
            for (var i = sequence.low; i < sequence.high; i++) {
                var result = sequence.results[i];
                // if this one is ready, process it
                if (result.ready) {
                    // increment counter past this result
                    ++sequence.low;
                    // remove this stored result
                    delete sequence.results[i];
                    // process this result
                    result.fn.apply(result.context, result.args);
                } else {
                    // if this one not ready, then nothing to do yet
                    break;
                }
            }
        };
    }
    
    // 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.

提交回复
热议问题