3-5 jQuery回调对象
本节编程练习不计算学习进度,请电脑登录imooc.com操作

jQuery回调对象

jQuery.Callbacks一般开发者接触的很少,虽然jQuery向开发者提供了外部接口调用,但是$.Callbacks()模块的开发目的是为了给内部$.ajax() 和 $.Deferred()模块提供统一的基本功能组件。它可以用来作为类似基础定义的新组件的功能。

jQuery.Callbacks是jquery在1.7版本之后加入的,是从1.6版中的_Deferred对象中抽离的,主要用来进行函数队列的add、remove、fire、lock等操作,并提供once、memory、unique、stopOnFalse四个option进行一些特殊的控制。

这个函数常见的应用场景是事件触发机制,也就是设计模式中的观察者模式的发布、订阅机制,目前Callbacks对象用于queue、ajax、Deferred对象中,本小节主要是一些简单的例子去理解的使用。

我们看官网提供的demo:

function fn1(value) {
  console.log(value);
}

function fn2(value) {
  fn1("fn2 says: " + value);
  return false;
}

可以将上述两个方法作为回调函数,并添加到 $.Callbacks 列表中,并按下面的顺序调用它们:

var callbacks = $.Callbacks();
callbacks.add(fn1);
// outputs: foo!
callbacks.fire("foo!");
callbacks.add(fn2);
// outputs: bar!, fn2 says: bar!
callbacks.fire("bar!")

这样做的结果是,当构造复杂的回调函数列表时,将会变更很简单。可以根据需要,很方面的就可以向这些回调函数中传入所需的参数。

上面的例子中,我们使用了 $.Callbacks() 的两个方法: .add() 和 .fire()。 .add() 和 .fire() .add() 支持添加新的回调列表, 而.fire() 提供了一种用于处理在同一列表中的回调方法的途径。

另一种方法是$.Callbacks 的.remove()方法,用于从回调列表中删除一个特定的回调。下面是.remove()使用的一个例子:

var callbacks = $.Callbacks();
callbacks.add( fn1 );
// outputs: foo!
callbacks.fire( "foo!" );
callbacks.add( fn2 );
// outputs: bar!, fn2 says: bar!
callbacks.fire( "bar!" );
callbacks.remove( fn2 );
// only outputs foobar, as fn2 has been removed.
callbacks.fire( "foobar" );

这个运用内部就是观察者模式的一种设计实现,只是相对比较复杂。我们看看jQuery的回调函数到底为哪些模块服务?

异步队列模块:

Deferred: function(func) {
  var tuples = [
    // action, add listener, listener list, final state
    ["resolve", "done", jQuery.Callbacks("once memory"), "resolved"],
    ["reject", "fail", jQuery.Callbacks("once memory"), "rejected"],
    ["notify", "progress", jQuery.Callbacks("memory")]
  ],………….

队列模块

_queueHooks: function(elem, type) {
  var key = type + "queueHooks";
  return data_priv.get(elem, key) || data_priv.access(elem, key, {
    empty: jQuery.Callbacks("once memory").add(function() {
      data_priv.remove(elem, [type + "queue", key]);
    })
  });
}

Ajax模块

ajax: function(url, options) {
  //省略代码
  deferred = jQuery.Deferred(),
  completeDeferred = jQuery.Callbacks("once memory")
    ..............
}

不难发现jQuery.Callbacks还提供“once memory”等参数用来处理:

   ☑  once: 确保这个回调列表只执行( .fire() )一次(像一个递延 Deferred)。

   ☑  memory: 保持以前的值,将添加到这个列表的后面的最新的值立即执行调用任何回调 (像一个递延 Deferred)。

   ☑  unique: 确保一次只能添加一个回调(所以在列表中没有重复的回调)。

   ☑  stopOnFalse: 当一个回调返回false 时中断调用。

var callbacks = $.Callbacks('once');

callbacks.add(function() {
  alert('a');
})

callbacks.add(function() {
  alert('b');
})

callbacks.fire(); //输出结果: 'a' 'b'
callbacks.fire(); //未执行

once的作用是使callback队列只执行一次。

OK,我们大概知道这个是干嘛用的了,可以开始上正菜了,(下一节开始噢!)

任务

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <script src="http://img1.sycdn.imooc.com//down/540812440001e40e00000000.js" type="text/javascript"></script>
  6. <title></title>
  7. </head>
  8. <body>
  9.  
  10. <script type="text/javascript">
  11.  
  12. function show(data) {
  13. $("body").append('<li>' + data + '</li>')
  14. }
  15.  
  16. function fn1(value) {
  17. show(value);
  18. }
  19.  
  20. function fn2(value) {
  21. fn1("fn2 says: " + value);
  22. return false;
  23. }
  24.  
  25. var callbacks = $.Callbacks();
  26. callbacks.add(fn1);
  27. // outputs: foo!
  28. callbacks.fire("foo!");
  29. callbacks.add(fn2);
  30. // outputs: bar!, fn2 says: bar!
  31. callbacks.fire("bar!");
  32.  
  33. </script>
  34.  
  35. </body>
  36. </html>
下一节