技术开发 频道

jQuery中的Deferred对象详解

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

  deferred对象的另一大好处,就是它允许你为多个事件指定一个回调函数,这是传统写法做不到的。

  请看下面的代码,它用到了一个新的方法$.when():

  $.when($.ajax("test1.html"), $.ajax("test2.html"))

  .done(
function(){ alert("哈哈,成功了!"); })

  .fail(
function(){ alert("出错啦!"); });

  (运行代码示例4)

  这段代码的意思是,先执行两个操作$.ajax("test1.html")和$.ajax("test2.html"),如果成功了,就运行done()指定的回调函数;如果有一个失败或都失败了,就执行fail()指定的回调函数。

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

  deferred对象的最大优点,就是它把这一套回调函数接口,从ajax操作扩展到了所有操作。也就是说,任何一个操作----不管是ajax操作还是本地操作,也不管是异步操作还是同步操作----都可以使用deferred对象的各种方法,指定回调函数。

  我们来看一个具体的例子。假定有一个很耗时的操作wait:

  var wait = function(){

  var tasks
= function(){

  alert(
"执行完毕!");

  };

  setTimeout(tasks,
5000);

  };

  我们为它指定回调函数,应该怎么做呢?

  很自然的,你会想到,可以使用$.when():

  $.when(wait())

  .done(
function(){ alert("哈哈,成功了!"); })

  .fail(
function(){ alert("出错啦!"); });

  但是,有一个问题。$.when()的参数只能是deferred对象,所以必须对wait进行改写:

  var dtd = $.Deferred(); // 新建一个deferred对象

  var wait
= function(dtd){

  var tasks
= function(){

  alert(
"执行完毕!");

  dtd.resolve();
// 改变deferred对象的执行状态

  };

  setTimeout(tasks,
5000);

  return dtd.promise();

  };

  这里有两个地方需要注意。

  首先,最后一行不能直接返回dtd,必须返回dtd.promise()。原因是jQuery规定,任意一个deferred对象有三种执行状态----未完成,已完成和已失败。如果直接返回dtd,$.when()的默认执行状态为"已完成",立即触发后面的done()方法,这就失去回调函数的作用了。dtd.promise()的目的,就是保证目前的执行状态----也就是"未完成"----不变,从而确保只有操作完成后,才会触发回调函数。

  其次,当操作完成后,必须手动改变Deferred对象的执行状态,否则回调函数无法触发。dtd.resolve()的作用,就是将dtd的执行状态从"未完成"变成"已完成",从而触发done()方法。

  最后别忘了,修改完wait之后,调用的时候就必须直接传入dtd参数。

  $.when(wait(dtd))

  .done(
function(){ alert("哈哈,成功了!"); })

  .fail(
function(){ alert("出错啦!"); });

  (运行代码示例5)

  六、普通操作的回调函数接口(中)

  除了使用$.when()为普通操作添加回调函数,还可以使用deferred对象的建构函数$.Deferred()。

  这时,wait函数还是保持不变,我们直接把它传入$.Deferred():

  $.Deferred(wait)

  .done(
function(){ alert("哈哈,成功了!"); })

  .fail(
function(){ alert("出错啦!"); });

  (运行代码示例6)

  jQuery规定,$.Deferred()可以接受一个函数作为参数,该函数将在$.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);

  (运行代码示例7)

  这里的关键是dtd.promise(wait)这一行,它的作用就是在wait对象上部署Deferred接口。正是因为有了这一行,后面才能直接在wait上面调用done()和fail()。

0
相关文章