0

我有一个基本上看起来像这样的函数:

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。所以我删除了return dfd。并将它放在每个 ajax 处理函数的最后,以确保在 Ajax 完成之前不会返回它。:

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

然后它根本不起作用。我很困惑!有人可以向我解释为什么我的 deferred 不能在 ajax 成功和错误处理程序中,以及为什么即使我的 deferred 对象在 Ajax 完成然后被解决或拒绝之前被触发,它似乎也返回了?这怎么可能呢?

编辑:这个问题直接链接到我之前的未回答和更复杂的功能: 延迟对象的问题

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

4

5 回答 5

1

$.ajax returns a Deferred object, so you only need to return it.

return $.ajax(...

于 2012-09-12T11:05:21.717 回答
1

Your call to defTest will return as soon as your ajax call is started. It will not wait until deferred is resolved or not.

But you are perfectly able to do what you want:

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

It will print deferred done when deferred is finally resolved.

By the way, as suggested by xdazz, $.ajax returns already a Deferred.

于 2012-09-12T11:07:00.440 回答
1

there are many questions like this
the AJAX request is async in nature so in the first example when you were returning it in the last line.
it dosent wait for the async ajax to complete
and in the second case the function is already over and putting return in success would obviously not return anything as you are not calling the method assigned to success event directly
UPDATE:- after the comment
because after returning the deffered object you are doing defTest().then(.....);
so the function inside the then handler will obviously be fired when the deffered object is resolved.
probably you should check the value of the deffered object as soon as you return it and not using .then() and you will get what mistake you are making here
Update 2 -
have a look here http://jsfiddle.net/BtEKa/ im getting predictable results

于 2012-09-12T11:07:15.603 回答
1

当然,它马上就回来了,这就是重点。通常情况下,一个会返回延迟对象的承诺成员——尽管您可以返回延迟对象并在调用此函数的代码中使用 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
    });
});

我希望我没有错过你的观点,但我喜欢将返回的承诺视为我以后可以一次又一次使用的数据源,并且我指定的 .then() 回调只有在返回响应时才会执行.

作为旁注,我很确定随着 jQuery 更接近承诺标准,.done()、.pipe()、.fail() 和 .progress() 应该替换为使用 .then(successCb, failCb , 进展Cb)。

于 2013-03-24T17:59:21.560 回答
0

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

承诺 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); });
于 2013-01-17T18:41:51.577 回答