首页 > 代码库 > javascript --- jQuery --- Deferred对象

javascript --- jQuery --- Deferred对象

javascript --- jQuery --- Deferred对象

 


javascript的函数式编程是多么引人入胜,
jQuery使代码尽可能的精简,intelligent!


defer - 必应词典:v.迁延;听从;扣存;【军】使延期入伍
所以deferred对象的含义就是"延迟"到未来某个点再执行。

jQuery的官方文档给出了用jQuery.ajax()发送请求的基本方式
http://api.jquery.com/jQuery.ajax/
Example: Save some data to the server and notify the user once it‘s complete.

服务端需要接收数据,这里为了方便起见,我们请求一个静态文件sample.html
sample.html的内容如下:
\jQuery_Deferred\sample.html

<!DOCTYPE html><html><body>    Ajax请求返回的数据!</body></html>

这里的ajax方法请求的是静态文件sample.html
\jQuery_Deferred\deferred1.html

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title>Ajax Example</title>    <script src="jquery-2.1.1.js"></script></head><body><script>    $.ajax({        type: "POST",        url: "sample.html",        data: { name: "John", location: "Boston" }    }).done(function (msg) {        alert("Data Saved: " + msg);    });</script></body></html>


用浏览器打开后,可以看到如下的结果:picture

本文参考了阮一峰的日志:
http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html
deferred对象彻底改变了在jQuery中使用ajax
如果对ajax陌生,可以参考我以前写的日志:
http://www.cnblogs.com/kodoyang/p/Javascript_Ajax_XMLHttpRequest_Encapsulation.html

deferred对象就是jQuery的回调函数解决方案
下面是阮一峰博客的原文:

{开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。  其中,既有异步的操作(比如ajax读取服务器数据),  也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。通常的做法是,为它们指定回调函数(callback)。  即事先规定,一旦它们运行结束,应该调用哪些函数。  它解决了如何处理耗时操作的问题,  对那些操作提供了更好的控制,以及统一的编程接口。}

jQuery的ajax的传统写法如下:
jQuery的在线API 文档: http://jquery.cuishifeng.cn/
\jQuery_Deferred\deferred2.html

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title>Traditional Ajax</title>    <script src="jquery-2.1.1.js"></script></head><body><script>    $.ajax({        url: "test.html",        context: document.body,        success: function () {            $(this).addClass("done");        }    });</script></body></html>

\jQuery_Deferred\test.html

<p>success data!</p>

使用Deferred对象的链式操作,写法如下:
\jQuery_Deferred\deferred3.html

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title>Deferred Ajax</title>    <script src="jquery-2.1.1.js"></script></head><body>    <script>        $.ajax("test1.html")                .done(function(data){                    alert(data);                })                .fail(function(){                    alert("error!");                });    </script></body></html>

这里$.ajax()返回的是deferred对象

deferred对象允许自由添加多个回调函数
\jQuery_Deferred\deferred4.html

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title>Deferred add callback function</title>    <script src="jquery-2.1.1.js"></script></head><body><script>    $.ajax("test.html")            .done(function(data){                alert(data);            })            .fail(function(){                alert("error!");            })            .done(function(){                alert("haha, success!");            });</script></body></html>

deferre对象允许为多个事件指定一个回调函数
当两个操作都返回成功时,运行done()指定的回调函数

\jQuery_Deferred\deferred5.html

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title>above one request</title>    <script src="jquery-2.1.1.js"></script></head><body><script>    $.when($.ajax("test.html"), $.ajax("sample.html"))            .done(function(){                alert("哈哈,成功了!");            })            .fail(function(){                alert("出错啦!");            });</script></body></html>

使用普通操作的回调函数接口
\jQuery_Deferred\deferred6.html

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title>general function</title>    <script src="jquery-2.1.1.js"></script></head><body><script>    var wait = function(){        setTimeout(function(){            alert("执行完毕!");        }, 5000);    }</script></body></html>

我们应该怎样为它指定回调函数?
$.ajax返回的是deferred对象,所以可以链式调用

具体的细节可以查看阮一峰的日志,我这里给出最后的写法:
\jQuery_Deferred\deferred7.html

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title>final code</title>    <script src="jquery-2.1.1.js"></script></head><body><script>    /**     * Deferred对象有三种执行状态:     * 未完成:     *      继续等待,或者调用progress()方法指定的回调函数     * 已完成:     *      deferred.resolve() 调用后     *      deferred对象立刻调用done()方法指定的回调函数     * 已失败:     *      deferred.reject() 调用后     *      调用fail()方法指定的回调函数     *     * Deferred.promise函数:     *      避免Deferred对象的“执行状态”在外部发生改变     *      它的作用是,在原来的deferred对象上返回另一个deferred对象,     *      后者只开放与改变执行状态无关的方法(比如done()方法和fail()方法),     *      屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),     *      从而使得执行状态不能被改变。     *     * @returns 不能改变执行状态的Deferred对象     */    function wait(){        // 在函数内部,新建一个Deferred对象        var deferred = $.Deferred();        setTimeout(function(){            alert("执行完毕!");            // 改变Deferred对象的执行状态            deferred.resolve();        }, 5000);        // 返回promise对象        return deferred.promise();    }    /**     * 接受一个Deferred对象,     * 当检测到对象的执行状态发生改变后,调用相应的函数     */    $.when(wait())            .done(function(){                alert("hahah, 成功了!");            })            .fail(function(){                alert("aaouu,出错了!")            });</script></body></html>

最后介绍一下Deferred.alway()函数
不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。
\jQuery_Deferred\deferred8.html

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title>reject then always</title>    <script src="jquery-2.1.1.js"></script></head><body><script>    /**     * 这个方法也是用来指定回调函数的,它的作用是,     * 不管调用的是deferred.resolve()还是deferred.reject(),     * 最后总是执行。     */    $.when($.ajax("test1.html"))            .always(function(data){                alert("已执行:" + data);            });</script></body></html>

 

 

请关注我的日志:http://www.cnblogs.com/kodoyang/

For Better Programming!

 

javascript --- jQuery --- Deferred对象