在jQuery.AJAX的上下文中理解jQuery.Deferred(再次)

时间:2014-05-27 16:14:40

标签: javascript jquery ajax jquery-deferred

我承认,尽管经过几个小时的阅读和尝试,我基本上无法掌握一般的延期承诺和异步。

我的目标是真实的,非常简单:将一些数据发送到服务器,并有条件地响应响应的内容。

响应始终是包含saveerror键的JSON对象:

{ "save": true, "error":false} 
// or
{ "save" : false, 
  "error" : "The server has run off again; authorities have been notifed."}

我已经尝试了来自jQuery API,其他stackexchange答案,教程等的数十个和几十个变体。这些示例似乎都关注本地异步活动。当我需要的是能够在AJAX请求完成并返回响应时知道某些能力,我可以检查并做出决定,或者知道它失败了。下面,我用评论来解释我的想法,这样有人可以告诉我我失败的地方。

知道这是一个转贴;在理解这一点时,我显然比平均水平更差。

var postData = {"id":7, "answer":"Ever since I went to Disneyland..."};

    /* when(), as I understand it, should fire an event to be 
       responded to by then() when it's contents have run their course */

var result = $.when(
       /* here I believe I'm supposed to assert what must complete 
          before the when() event has fired and before any chained 
          functions are subsequently called */

             /* this should return a jqXHR object to then(), which is,
                I'd thought, a queue of functions to call, in order, 
                UPON COMPLETION of the asynchronous bit */
             $.post("my/restful/url", postData))
    .then( function() {
        /* since "this" is the jqXHR object generated in the $.post()
           call above, and since it's supposed to be completed by now,
           it's data key should be populated by the server's response—right? */
        return this.data;
    });

    // alas, it isn't
    console.log(result.data);
    // >> undefined

我能找到的大多数例子都讨论了超时功能;但是,正如我所理解的那样,这似乎是一个故障保护措施,可以随意决定异步部分何时失败,而不是延迟时间以便请求完成。实际上,如果我们所能做的只是等待它,那么与同步请求有什么不同呢?

我甚至会链接到 new read-mes,教程等,如果它们以不同的方式覆盖材料,请使用jQuery API中修改过的示例之外的其他内容,或通过异步mirk帮助这个流口水的白痴;这是我迄今为止一直在阅读的地方:

jQuery API: Deferred
JQuery Fundamentals
jQuery Deferreds promises asynchronous bliss (blog)
StackOverflow: timeout for function (jQuery)


更新

这是对以下@Kevin B的回应:

我试过了:

var moduleA = {
        var moduleB = {
                    postData: {"id":7, "answer":"Ever since I went to Disneyland..."};
                    save: function() {
                       return $.post("path/to/service", postData, null, "JSON");
                    }
        };
        var result = this.moduleB.save();
        result.done(function(resp) {
            if (resp.saved == true) {
                // never reached before completion
                console.log("yahoo");
            } else {
                console.log("Error: " + resp.error);
                // >> undefined
            }
        });

}

3 个答案:

答案 0 :(得分:1)

您的代码过于复杂。无论您创建/使用多少延迟/承诺,您都无法将数据传递到回调之外(您的示例会创建3个不同的延迟对象!)

使用完成回调。

var postData = {"id":7, "answer":"Ever since I went to Disneyland..."};
$.post("my/restful/url", postData).done(function (result) {
    console.log(result.save, result.error);
});

答案 1 :(得分:0)

您似乎误解了异步请求,Promise模式和将函数作为参数传递的Javascripts机制。

要了解代码中发生了什么,我建议您使用调试器并在代码中设置一些断点。或者,在代码中添加一些console.logs。通过这种方式,您可以看到程序的流程,并可能更好地理解它。还要确保在then()方法中记录作为参数传递的函数的参数,以便了解传递的内容。

答案 2 :(得分:-1)

好吧,你得到了一半。问题是当你执行console.log时,承诺尚未实现,promises的异步性质允许代码在ajax操作完成之前执行。结果是延迟而不是值,你需要用.done而不是.then处理你的承诺,如果你想要返回一个值,否则你将继续通过承诺。

所以说

var result={};
  $.when(
      $.post("my/restful/url", postData))
        .done( function(data) {
        result.data=data;
  });
// here result is an object and data is a undefined since the promised has no yet been resolve.
console.log(result.data);