请大牛解答Jquery AJAX如何使用Promise/Deferred实现顺序执行?

ooxxoo
  • 327

因为每次get到数据是下次请求的参数
目前我是层层嵌套,不好维护,可读性也很差,大致流程如下:

function get(){
    $.ajax({
        url:'test.php',
        success:function(){
            $.ajax({
                url:'test1.php',
                success:function(){
                    $.ajax({
                        url:'test2.php',
                        success:function(){
                            $.ajax({
                                url:'test3.php',
                                success:function(){
                                    //TODO
                                }
                            })
                        }
                    })
                }
            })
        }
    })
}

for(i=0;i<list.length;i++){
    get()
}

大牛勿笑,就是这么蛋疼,希望能帮帮我,谢谢

回复
阅读 6.8k
4 个回答
function get(){
    $.ajax({
        url:'test.php'
    }).then(function(){
        return $.ajax({ url:'test1.php' });
    }).then(function(){
        return $.ajax({ url:'test2.php' });
    }).then(function(){
        return $.ajax({ url:'test3.php' });
    }).then(function(){
        //TODO here
    });
}

for(i=0;i<list.length;i++){
    get()
}
$.ajax("test1.php").then(function(data) {
    // data 是 test1.php 的返回值
    return $.ajax("test2.php");
}).then(function(data) {
    // data 是 test2.php 的返回值
    return $.ajax("test3.php");
}).then(function(data) {
    return $.ajax("test4.php");
});

也说一下除了最常见的Promise之外的另一种handle async的做法。
例子用的这个lib比较合适用在node上的,不过browser也可用,只是用來解说一下就随便一点吧。

caolan/async

...
<script src="https://cdnjs.cloudflare.com/ajax/libs/async/1.5.0/async.min.js"></script>
var wrapErrCb = function (cb) {
    return function () {
        cb(Array.prototype.slice.call(arguments));
    };
}

// 除了series之外还有waterfall, parallel, forever, iterate等等n种可选
/* series(tasks, [callback])
   Run the functions in the tasks array in series, each one running once the previous 
   function has completed. If any functions in the series pass an error to its 
   callback, no more functions are run, and callback is immediately called with the 
   value of the error. Otherwise, callback receives an array of results when tasks 
   have completed.
*/
async.series([
    function(callback) {
        $.ajax()
            .fail(wrapErrCb(callback))
            .done(callback.bind(null, null));
    },
    function(callback) {
            .fail(wrapErrCb(callback))
            .done(callback.bind(null, null));
    },
    function(callback) {
            .fail(wrapErrCb(callback))
            .done(callback.bind(null, null));
    },
    function(callback) {
            .fail(wrapErrCb(callback))
            .done(callback.bind(null, null));
    }
], function (err, results) {
    if (err) return console.log(err);
    // err会是null或是[jqXHR, textStatus, errorThrown]
    // err是null的话才会有results:
    // [
    //   [data, textStatus, jqXHR],
    //   [data, textStatus, jqXHR],
    //   [data, textStatus, jqXHR]
    // ]
});

请查看我写的gist, 代码如下

// test methods fun1 and fun2 for test
var fun1 = function () {
    var deferred = $.Deferred();

    setTimeout(function () {
        console.log('I am fun1');
        deferred.resolve();
    }, 1000);

    return deferred.promise();
}

var fun2 = function () {
    var deferred = $.Deferred();

    setTimeout(function () {
        console.log('I am fun2');
        deferred.resolve();
    }, 1000);

    return deferred.promise();
}

// make test jQuery asynchronous methods array
var arr = [fun1, fun2];

// This the target method for implementing that call jQuery asyn methods recursively
var recursive = function(i, arr) {
    return execute(arr[i]).then(function() {
        if (i + 1 < arr.length) {
            recursive(i + 1, arr);
        }
    });
    
    function execute(func) {
        return func();
    }
}

// run our test
recursive(0, arr);

至于你的代码,可以写成这样的:

function call1() {
    return $.ajax({url:'test1.php'});
}
function call2() {
    return $.ajax({url:'test1.php'});
}

arr = [call1, call2];

var recursive = function(i, arr) {
    return execute(arr[i]).then(function() {
        if (i + 1 < arr.length) {
            recursive(i + 1, arr);
        }
    });
    
    function execute(func) {
        return func();
    }
}

// run our test
recursive(0, arr);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏