Chaining ajax requests with jQuery's deferred

后端 未结 7 2271
天涯浪人
天涯浪人 2021-02-19 19:46

I have a web app which must call the server multiple times. So far, I had a long nested callback chain; but I would like to use jQuery\'s when,then etc

相关标签:
7条回答
  • 2021-02-19 20:09

    I thought I would leave this little exercise here for anyone who may find it useful, we build an array of requests and when they are completed, we can fire a callback function:

    var urls = [{
        url: 'url1',
        data: 'foo'
    }, {
        url: 'url2',
        data: 'foo'
    }, {
        url: 'url3',
        data: 'foo'
    }, {
        url: 'url4',
        data: 'foo'
    }];
    var requests = [];
    var callback = function (result) {
        console.log('done!');
    };
    
    var ajaxFunction = function () {
        for (var request, i = -1; request = urls[++i];) {
            requests.push($.ajax({
                url: request.url,
                success: function (response) {
                    console.log('success', response);
                }
            }));
        }
    };
    
    // using $.when.apply() we can execute a function when all the requests 
    // in the array have completed
    $.when.apply(new ajaxFunction(), requests).done(function (result) {
        callback(result)
    });
    
    0 讨论(0)
  • 2021-02-19 20:11

    As an update:

    With modern jquery (1.8+) you don't need the preliminary when because get returns a Deferred Promise.

    Also, pipe is deprecated. Use then instead. Just be sure to return the result of the new get which becomes the Promise attached to by subsequent then/*done*/fail calls.

    So:

    $.get('pages/run-tool.html')
    .then (function (args) { // this will run if the above .get succeeds
        // This works fine
        alert(args);
        $('#content').replaceWith (args);
        $('#progress-bar').progressbar ({value: 0});
    })
    .then (function() { // this will run after the above then-handler (assuming it ran)
        return $.get('pages/test.html'); // the return value creates a new Deferred object
    })
    .done (function(args) { // this will run after the second .get succeeds (assuming it ran)
        alert (args); 
    });
    
    0 讨论(0)
  • 2021-02-19 20:22

    All three callbacks (the two with then and the one with done) are applied to the same request – the original when call. This is because then returns the same Deferred object, rather than a new one, so that you can add multiple event handlers.

    You need to use pipe instead.

    $
    .when ($.get('pages/run-tool.html'))
    .then (function (args)
    {
        // This works fine
        alert(args);
        $('#content').replaceWith (args);
        $('#progress-bar').progressbar ({value: 0});
    })
    .pipe (function() { 
        return $.get('pages/test.html'); // the return value creates a new Deferred object
    })
    .done (function(args)
    {
        alert (args);
    });
    
    0 讨论(0)
  • 2021-02-19 20:22

    My way is to apply callback function:

    A(function(){
           B(function(){
                C()})});
    

    where A, B can be written as

    function A(callback)
    $.ajax{
        ...
        success: function(result){
            ...
            if (callback) callback();
       }
    }
    
    0 讨论(0)
  • 2021-02-19 20:24
    <script type="text/javascript">
    
        var promise1 = function () {
            return new
            $.Deferred(function (def) {
                setTimeout(function () {
                    console.log("1");
                    def.resolve();
                }, 3000);
            }).promise();
        };
    
        var promise2 = function () {
            return new
            $.Deferred(function (def) {
                setTimeout(function () {
                    console.log("2");
                    def.resolve();
                }, 2000);
            }).promise();
        };
    
        var promise3 = function () {
            return new
            $.Deferred(function (def) {
                setTimeout(function () {
                    console.log("3");
                    def.resolve();
                }, 1000);
            }).promise();
        };
    
        var firstCall = function () {
            console.log("firstCall");
            $.when(promise1())
            .then(function () { secondCall(); });
        };
    
        var secondCall = function () {
            console.log("secondCall")
            $.when(promise2()).then(function () { thirdCall(); });
        };
    
        var thirdCall = function () {
            console.log("thirdCall")
            $.when(promise3()).then(function () { console.log("done"); });
        };
    
    
        $(document).ready(function () {
            firstCall();
        });
    </script>
    
    0 讨论(0)
  • 2021-02-19 20:28

    Here is an wonderfully simple and highly effective AJAX chaining / queue plugin. It will execute you ajax methods in sequence one after each other.

    It works by accepting an array of methods and then executing them in sequence. It wont execute the next method whilst waiting for a response.

    //--- THIS PART IS YOUR CODE -----------------------

    $(document).ready(function () {

    var AjaxQ = [];
    AjaxQ[0] = function () { AjaxMethod1(); }
    AjaxQ[1] = function () { AjaxMethod2(); }
    AjaxQ[3] = function () { AjaxMethod3(); }
    
    //Execute methods in sequence
    $(document).sc_ExecuteAjaxQ({ fx: AjaxQ });
    

    });

    //--- THIS PART IS THE AJAX PLUGIN -------------------

    $.fn.sc_ExecuteAjaxQ = function (options) {

    //? Executes a series of AJAX methods in dequence
    
    var options = $.extend({
    
        fx: [] //function1 () { }, function2 () { }, function3 () { }
    
    }, options);
    
    if (options.fx.length > 0) {
    
        var i = 0;
    
        $(this).unbind('ajaxComplete');
        $(this).ajaxComplete(function () {
    
            i++;
            if (i < options.fx.length && (typeof options.fx[i] == "function")) { options.fx[i](); }
            else { $(this).unbind('ajaxComplete'); }
    
        });
    
        //Execute first item in queue
        if (typeof options.fx[i] == "function") { options.fx[i](); }
        else { $(this).unbind('ajaxComplete'); }
    
    } 
    

    }

    0 讨论(0)
提交回复
热议问题