Jquery 嵌套延迟等待 AJAX 响应

Jquery nested deferred wait for AJAX response

有 deferred 的函数在里面调用另一个 deferred 的函数:

var state = true;

var construct = function() {
    var dfd = $.Deferred();
    dfd
        .then(function() {
            return wakeUp();
        })
        .then(function() {
            return makeCoffee();
        })
        .then(function() {
            return conquireTheWorld();
        })
        .then(function() {
            console.log("I'm done");
        });
    dfd.resolve();
}

var wakeUp           = function() {console.log('Woke up');}

var makeCoffee       = function() {console.log('Made some coffee');}

var conquireTheWorld = function() {
    var dfd = $.Deferred();
    if (state) {
        dfd.then(function() {
            return $.when(someAjax('http://babeljs.io')).done(function() {console.log("World done with AJAX");})
        });
    } else {
        dfd.then(function() {
            console.log("World done in a simple way");
        });
    }
    dfd
        .then(function() {
            console.log("Moon done too");
        });
    return dfd.resolve();
}

var someAjax = function(url) {
    return $.ajax({
        type: 'GET',
        url: url
    });
}

不幸的是,在这种情况下,它卡在了conquireTheWorld函数中:.done部分$.when根本没有运行,其他部分在之后执行parent一个。有控制台输出:

Woke up
Made some coffee
Moon done too //executed before ajax request complete
I'm done //executed before conquerTheWorld function ajax
World done with AJAX

如何等待ajax请求?我试图删除 $.when 并在另一个 .then 语句中处理(没有改变),或者 return dfd.promise() 而不是 dfd.resolve() (它卡在那个函数中)。如何正确操作?

许下诺言:

var promise = $.Deferred().resolve().promise();

链可以在单个表达式中形成如下:

var p = promise.then(fnA).then(fnB).then(fnC);

下面是等价的——形成一个链"by assigment":

var p;
p = promise.then(fnA);
p = p.then(fnB);
p = p.then(fnC);

以下不等价 - fnAfnBfnC只依赖于promise,不依赖于每个其他.

promise.then(fnA);
promise.then(fnB);
promise.then(fnC);

问题的 conquireTheWorld() 是用 "not equivalent" 格式写的。

console.log("World done with AJAX") 取决于 AJAX.

上的初始承诺(实际上是 Deferred)and

与此同时,console.log("Moon done too")(和调用者中的 console.log("I'm done"))都只依赖于最初的承诺,赢得比赛超过AJAX-延迟消息。

要修复,请将 conquireTheWorld() 转换为 "equivalent" 模式,方法是进行赋值并返回结果承诺,而不是初始承诺。

编辑:

完整:

var conquireTheWorld = function() {
    var promise = $.when(); // shorthand way to create a resolved jQuery promise.
    if (state) {
        promise = promise.then(function() {
            return someAjax('http://babeljs.io').then(function() { console.log("World done with AJAX"); });
        });
    } else {
        promise = promise.then(function() {
            console.log("World done in a simple way");
        });
    }
    promise = promise.then(function() {
        console.log("Moon done too");
    });
    return promise;
}

有更好的方法可以达到相同的目的,但这是问题中代码的更正版本。