今天学习jQuery API的时候看到deferred部分,以前也没有接触使用过,看的毫无头绪,于是找资料学习了一番。
deferred对象代表了将要完成的某种操作,并提供了一些方法,帮助用户使用。它是jQuery对Promises接口的实现。由于JavaScript单线程的特点,如果某个操作耗时很长,其他操作就必需排队等待。为了避免整个程序失去响应,通常的解决方法是将那些排在后面的操作,写成“回调函数”(callback)的形式。这样做虽然可以解决问题,但是有一些显著缺点:
回调函数往往写成函数参数的形式,导致函数的输入和输出非常混乱,整个程序的可阅读性差;
回调函数往往只能指定一个,如果有多个操作,就需要改写回调函数。
整个程序的运行流程被打乱,除错和调试的难度都相应增加。
Promises就是为了解决这些问题而提出的,它的主要目的就是取代回调函数,成为非同步操作的解决方案。它的核心思想就是让非同步操作返回一个对象,其他操作都针对这个对象来完成。比如,假定ajax操作返回一个Promise对象。
1 var promise = get(‘http://www.example.com‘);
然后,Promise对象有一个then方法,可以用来指定回调函数。一旦非同步操作完成,就调用指定的回调函数。
1 promise.then(function (content) {
2 console.log(content)
3 });
可以将上面两段代码合并起来,这样程序的流程看得更清楚。
1 get(‘http://www.example.com‘).then(function (content) {
2 console.log(content)
3 });
在1.7版之前,jQuery的Ajax操作采用回调函数。
1 $.ajax({
2 url:"/echo/json/",
3 success: function(response){
4 console.info(response.name);
5 }
6 });
1.7版之后,Ajax操作直接返回Promise对象,这意味着可以用then方法指定回调函数。
1 $.ajax({
2 url: "/echo/json/",
3 }).then(function (response) {
4 console.info(response.name);
5 });
除此之外,deferred对象的第二个好处,就是它允许你自由添加多个回调函数。
1 $.ajax("test.html")
2 .done(function(){ alert("哈哈,成功了!");} )
3 .fail(function(){ alert("出错啦!"); } )
4 .done(function(){ alert("第二个回调函数!");} );
deferred对象的第三个好处,就是它允许你为多个事件指定一个回调函数,这是传统写法做不到的。
1 $.when($.ajax("test1.html"), $.ajax("test2.html"))
2 .done(function(){ alert("哈哈,成功了!"); })
3 .fail(function(){ alert("出错啦!"); });
这段代码的意思是,先执行两个操作$.ajax("test1.html")和$.ajax("test2.html"),如果都成功了,就运行done()指定的回调函数;如果有一个失败或都失败了,就执行fail()指定的回调函数。
deferred对象有多种方法可以使用,下面做一个总结:
(1) $.Deferred() 生成一个deferred对象。
(2) deferred.done() 指定操作成功时的回调函数
(3) deferred.fail() 指定操作失败时的回调函数
(4) deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。
(5) deferred.resolve() 手动改变deferred对象的运行状态为"已完成",从而立即触发done()方法。
(6)deferred.reject() 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为"已失败",从而立即触发fail()方法。
(7) $.when() 为多个操作指定回调函数。
(8)deferred.then() 有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。
$.when($.ajax( "/main.php" ))
.then(successFunc, failureFunc );
如果then()有两个参数,那么第一个参数是done()方法的回调函数,第二个参数是fail()方法的回调方法。如果then()只有一个参数,那么等同于done()。
(9)deferred.always() 这个方法也是用来指定回调函数的,它的作用是,不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。
jQuery的deferred对象,古老的榕树,5-wow.com