在拒绝或解决之前返回的延迟对象?

时间:2012-09-12 11:03:08

标签: jquery deferred

我的功能基本上是这样的:

function defTest()
{
    var dfd = new jQuery.Deferred();
    $.ajax(
    {
        type: "GET",
        url: 'http://XXXX',
        cache: false,
        dataType: "json",
        success: function(data,status)
        {
            console.log('ajax done: success');
            dfd.resolve();
        },
        error: function(data,status)
        {
            console.log('ajax done: fail');
            dfd.reject();

        }
    });
    console.log('about to return dfd');
    return dfd;    
}

我称之为:

defTest().then(.....);

控制台日志产生: 即将返回dfd code.js:106 ajax done:success code.js:96

令我困惑的是代码似乎有效。仍然在ajax完成之前返回dfd。所以我删除了返回dfd。并将其放在每个ajax处理函数中,以确保在Ajax完成之前不会返回它。:

success: function(data,status)
{
    console.log('ajax done: success');
    dfd.resolve();
    return dfd;
}

然后它根本不起作用。我很迷惑!有人可以向我解释为什么我的deferred不能在ajax成功和错误处理程序中以及为什么它工作即使看起来我的延迟对象返回,即使它在Ajax完成之前被解雇然后被解决或拒绝?怎么可能呢?

编辑: 此问题与我之前未解决的问题和更复杂的功能直接相关: Problems with deferred object

这就是为什么我不能只是“返回ajax(...)”,因为我的真实函数包含其他ajax调用,这些调用将一个结果传递给调用者。

5 个答案:

答案 0 :(得分:1)

$.ajax返回一个Deferred对象,因此您只需要返回它。

return $.ajax(...

答案 1 :(得分:1)

当您的ajax呼叫启动后,您defTest的来电将立即返回。 它不会等到延迟解决后才会解决。

但你完全可以做你想做的事:

defTest().then(function() { console.log("deferred done"); })

最终解决延期时,它将打印deferred done

顺便说一句,正如xdazz所建议的那样,$.ajax已经返回了Deferred。

答案 2 :(得分:1)

有很多这样的问题 AJAX请求本质上是async,因此在第一个示例中,当您在最后一行返回时。
它等待async ajax完成。 在第二种情况下,函数已经结束并且返回成功显然不会返回任何内容,因为您没有直接调用分配给success事件的方法 更新: - 发表评论后
因为在您返回正在进行的deffered对象后defTest().then(.....);
所以当deffered对象被解析时,显然会触发then处理程序内的函数 可能你应该在退回deffered对象时立即检查.then()对象的值,而不是{{1}},你会在这里弄错了 更新2 -
看看这里http://jsfiddle.net/BtEKa/即可获得可预测的结果

答案 3 :(得分:1)

当然,它立即归还,这就是重点。但是,通常会返回延迟对象的promise成员 - 虽然您可以返回延迟对象并在调用此函数的代码中使用returnedDeferredObject.promise()。then()。

如果您的处理依赖于AJAX完成,则该处理将在返回的.promise()的.then()函数中进行。美妙之处在于异步处理正在进行中,您可以做其他不依赖于AJAX返回的事情。您可以将返回的.promise()传递给其他代码。

var mydata = somethingThatReturnsPromise(args);

// do a whole bunch of things

mydata.then(function (returnedReponse) {
    // do stuff with returnedResponse that doesn't require DOM ready
});

$(function () {
    mydata.then(function (returnedResponse) {
        // do DOM stuff with returnedPromise
    });
});

我希望我不会错过你的观点,但我想把这个返回的promise作为一个数据源,我可以在以后一次又一次地使用,而我指定的.then()回调只会被执行一次有一个返回的响应。

作为旁注,我很确定jQuery更多地遵循promise标准,.done(),. pipe(),. fail()和.progress()应该替换为.then( successCb,failCb,progressCb)。

答案 4 :(得分:0)

我相信你的问题是你要返回整个延迟对象,而不是那个对象的承诺。

在返回异步调用之前总是返回promise afiak,所以当你的最后一个console.log在PROMISE返回之前触发时,它会在ajax解析之前发生。

使用.then()也可能不是你想要的,因为无论延迟对象的状态是什么,它都会触发:http://api.jquery.com/deferred.then/

你可能想要.done()

试试这个:

function defTest()
{
    var dfd = $.Deferred();
    $.getJSON("http://XXXX").done(function(data,success){
      console.log('ajax done: success');
      dfd.resolve(data);
    }).fail( function(data,status) {
      console.log('ajax done: fail');
      dfd.reject();
    });
    console.log('about to return dfds promise');
    return dfd.promise;    
}
defTest().done(function(data){ console.log(data); });