【问题标题】:Jquery nested deferred wait for AJAX responseJquery嵌套延迟等待AJAX​​响应
【发布时间】:2017-04-20 14:56:50
【问题描述】:

有一个带有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 根本没有运行,其他部分在父函数之后执行。有控制台输出:

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 语句中处理(没有改变),或者返回 dfd.promise() 而不是 dfd.resolve() (它卡在那个函数中)。如何以正确的方式做到这一点?

【问题讨论】:

  • 哇。该功能可以简化为if (state) { return someAjax('http://babeljs.io').done(function () {console.log('ajax whatever');});} else { console.log('whatever'); } 过度使用方法。
  • @KevinB 在 if/else 语句之后我还有一个操作,这样我应该复制它或将它分离到另一个函数,不是吗?

标签: jquery ajax deferred


【解决方案1】:

承诺:

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

以下是不等价的 - fnAfnBfnC 仅依赖于 promise,而不是相互依赖。

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

问题的conquireTheWorld() 使用“不等价”模式编写。

console.log("World done with AJAX") 依赖于初始承诺(实际上是延迟)在 AJAX 上。

同时,console.log("Moon done too")(和调用者中的console.log("I'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;
}

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

【讨论】:

  • $.Deferred.resolve 不是函数 - 我遇到了这个错误。
  • 你的意思是 $.Deferred().resolve().promise() 吗?它也没有按预期工作。这是要运行的code,但在I'm done 输出之后仍然会出现ajax 响应。
  • 是的,$.Deferred()...。更典型的是,人们倾向于为已解决的 jQuery 承诺写 $.when()
  • 但它的行为不正确,就像我上面写的那样。有什么不“等效”的东西吗?我正在处理我在 conquireTheWorld() 中创建的一个承诺,但仍然没有等待。
  • 你没有按照我说的去做。你需要做作业。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 1970-01-01
  • 2014-03-11
  • 1970-01-01
  • 1970-01-01
  • 2013-11-24
相关资源
最近更新 更多