一、什么是deferred对象?

简单说,deferred对象就是jQuery的回调函数解决方案。deferred对象的含义就是”延迟”到未来某个点再执行。
它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口。

二、ajax操作的链式写法

传统写法:

$.ajax({
url: "baidu.com",
type: "get",
success: function() {
console.log("success");
},
error: function() {
console.log("error");
}
});

“< 1.5” 返回的是XHR对象,没法进行链式操作
“> 1.5” 返回的是deferred对象,可以进行链式操作
新的写法是这样的:

$.ajax({url:"baidu.com", type:"get"})
.done(function() {
console.log("success");
})
.fail(function() {
console.log("error");
});

采用链式写法以后,代码的可读性大大提高。

三、指定同一操作的多个回调函数

$.ajax({url:"baidu.com", type:"get"})
.done(function() {
console.log("success");
})
.fail(function() {
console.log("error");
})
.done(function() {
console.log("success,too");
});

回调函数可以添加任意多个,它们按照添加顺序执行。

四、为多个操作指定回调函数

$.when($.ajax("baidu.com"), $.ajax("google.com"))
  .done(function() {
console.log("success");
})
.fail(function() {
console.log("error");
});

如果都成功了,就运行done()指定的回调函数;
如果有一个失败或都失败了,就执行fail()指定的回调函数。

五、普通操作的回调函数接口

方式一:$.when()

var wait = function(dtd){
var tasks = function(){
console.log("执行完毕!");
dtd.resolve(); // 改变deferred对象的执行状态
  };
  setTimeout(tasks,5000);
return dtd;
};

如何为其制定回调函数

$.when(wait($.Deferred()))
.done(function() {
console.log("yes!");
})
.fail(function() {
console.log("fail!");
});

方式二:使用deferred对象的建构函数$.Deferred()

var wait = function(dtd){
var tasks = function(){
console.log("执行完毕!");
dtd.resolve(); // 改变deferred对象的执行状态
  };
  setTimeout(tasks,5000);
return dtd;
};

如何为其制定回调函数

$.Deferred(wait)
.done(function() {
console.log("yes!");
})
.fail(function() {
console.log("fail!");
});

PS:jQuery规定,.Deferred()可以接受一个函数名(注意,是函数名)作为参数,.Deferred()所生成的deferred对象将作为这个函数的默认参数。

方式三:直接在wait对象上部署deferred接口

var dtd = $.Deferred(); // 生成Deferred对象
var wait = function(dtd){
var tasks = function(){
  alert("执行完毕!");
  dtd.resolve(); // 改变Deferred对象的执行状态
  };
  setTimeout(tasks,5000);
};
dtd.promise(wait);
wait.done(function(){ alert("哈哈,成功了!"); })
  .fail(function(){ alert("出错啦!"); });
wait(dtd);

六、deferred.resolve()方法和deferred.reject()方法

deferred对象有三种执行状态:已完成,已失败和未完成。

  • 如果执行状态是”已完成”,deferred对象立刻调用done()方法指定的回调函数;【手动触发:dtd.resolve()】
  • 如果执行状态是”已失败”,调用fail()方法指定的回调函数;【手动触发:dtd.reject()】
  • 如果执行状态是”未完成”,则继续等待,或者调用progress()方法指定的回调函数。

PS:ajax操作,deferred对象会根据返回结果,自动改变自身的执行状态

七、deferred.promise()方法

在原来的deferred对象上返回另一个deferred对象,后者只开放与改变执行状态无关的方法(比如done()方法和fail()方法),屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),从而使得执行状态不能被改变。

var wait = function(dtd){
  var tasks = function(){
    console.log("执行完毕!");
dtd.resolve(); // 改变deferred对象的执行状态
  };
  setTimeout(tasks,5000);
return dtd.promise();
};

如何为其制定回调函数

$.when(wait($.Deferred()))
.done(function() {
console.log("yes!");
})
.fail(function() {
console.log("fail!");
});

总结

  • $.Deferred() 生成一个deferred对象。
  • deferred.done() 指定操作成功时的回调函数
  • deferred.fail() 指定操作失败时的回调函数
  • deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。
  • deferred.resolve() 手动改变deferred对象的运行状态为”已完成”,从而立即触发done()方法。
  • deferred.reject() 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为”已失败”,从而立即触发fail()方法。
  • $.when() 为多个操作指定回调函数。
    除了这些方法以外,deferred对象还有二个重要方法,上面的教程中没有涉及到。
  • deferred.then()
    有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。
      .when(.ajax( “/main.php” ))
      .then(successFunc, failureFunc );
    如果then()有两个参数,那么第一个参数是done()方法的回调函数,第二个参数是fail()方法的回调方法。如果then()只有一个参数,那么等同于done()。
  • deferred.always()
    这个方法也是用来指定回调函数的,它的作用是,不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。
      $.ajax( “test.html” )
      .always( function() { alert(“已执行!”);} );

参考地址:​​http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html​