Jquery嵌套延迟等待AJAX响应

Jquery嵌套延迟等待AJAX响应,jquery,ajax,deferred,Jquery,Ajax,Deferred,有一个函数使用deferred调用另一个函数,其中包含deferred: var state = true; var construct = function() { var dfd = $.Deferred(); dfd .then(function() { return wakeUp(); }) .then(function() { return makeCoffee();

有一个函数使用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函数:$.when的done部分根本不运行,而其他部分在父函数之后执行。有控制台输出:

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请求?我已尝试删除另一个.then语句中的$.when和process。语句没有任何更改,或者返回dfd.promise而不是dfd.resolve,因为它在该函数中阻塞。如何以正确的方式做这件事?

接受承诺:

var promise = $.Deferred().resolve().promise();
链可以在单个表达式中形成,如下所示:

var p = promise.then(fnA).then(fnB).then(fnC);
以下是等效的-链由分配形成:

var p;
p = promise.then(fnA);
p = p.then(fnB);
p = p.then(fnC);
以下情况并不等同——fnA、fnB和fnC仅依赖于承诺,而不是相互依赖

promise.then(fnA);
promise.then(fnB);
promise.then(fnC);
问题的关键在于,世界是以非等效模式书写的

使用AJAX完成的console.logWorld取决于最初的承诺(实际上是延迟的承诺)和AJAX

同时,console.logMoon-done和console.logI-m-done在调用者中都只依赖于最初的承诺,并赢得了AJAX延迟消息的竞争

要修复此问题,请通过赋值并返回结果承诺(而不是初始承诺)将conquireTheWorld转换为等效模式

编辑:

全文:

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;
}

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

whoa。该函数可以简化为if状态{return someAjax'http://babeljs.io“.donefunction{console.log'ajax whatever';};}else{console.log'whatever';}方法过度使用。@KevinB在if/else语句之后,我还有一个操作,这样我应该将它复制或分离到另一个函数,不是吗?$.Deferred.resolve不是一个函数-我犯了这个错误。你是说$.Deferred.resolve.promise吗?它也不像预期的那样工作。这是要运行的,但ajax响应仍然在我完成输出后出现。是的,$。延迟。。。。更典型的是,人们倾向于为一个已解决的jQuery承诺编写$。when。但它的行为并不正确,就像我在上面写的那样。有什么东西不等同于模式吗?我在conquireTheWorld中做出了一个承诺,但我仍然迫不及待。你没有按照我说的去做。你需要做作业。