jQuery.Callbacks(flags)

来源:互联网 发布:淘宝处女红坑了多少人 编辑:程序博客网 时间:2024/05/21 17:06

一个多用途的回调函数列表对象,提供一种强大的方式来管理回调函数列表。

  • 1.7 新增jQuery.Callbacks(flags)

    flags (String) 一个可选的列表标记字符串,字符串之间使用空格分隔。代表如何改变回调函数列表的行为。

jQuery $.ajax() 和 $.Deferred() 组件的内部会使用 $.Callbacks() 函数,来提供基本的功能。它可以用作定义新组件功能的简易基础。

$.Callbacks() 支持的方法包括 callbacks.add() , callbacks.remove() callbacks.fire() 和 callbacks.disable() .

开始学习

例如,有如下两个方法,分别叫做 fn1 和 fn2:

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

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

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

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

上面的例子中,我们使用了 $.Callbacks() 的两个方法: .add() 和 .fire()。 .add() 可以向回调函数列表中添加新的回调函数,fire() 可以向回调函数中传递参数,并执行回调函数。

$.Callbacks 支持的另一个方法是 remove(),它可以从回调函数列表中移除指定的回调函数。下面是使用 .remove() 的例子:

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

支持的标识

flags 参数是 $.Callbacks() 的可选参数,该参数是一个以空格分隔的字符串列表,代表如何改变回调函数列表的行为(例如,$.Callbacks( 'unique stopOnFalse' ))。

可用的标识:

  • once: 保证回调函数列表只能被 .fire() 一次。(就像延迟对象一样)
  • memory: 持续保留前一个值,在执行完 .fire() 之后添加的任何回调函数,当再次遇到 .fire() 时,会将“最新保持”的值作为参数,立刻调用最近添加的所有函数,然后再执行回调函数列表中的函数(就像延迟对象一样)。
  • unique: 保证一个回调函数只能被添加一次(也就是说,在回调函数列表中,没有重复的回调函数)。
  • stopOnFalse: 当回调函数返回 false 时,中断调用。

默认情况下,一个回调函数列表就像一个事件回调列表,可以被“调用”多次。

下面是一些理想情况下,使用 flags 的范例:

$.Callbacks( 'once' ):

var callbacks = $.Callbacks( "once" );callbacks.add( fn1 );callbacks.fire( "foo" );callbacks.add( fn2 );callbacks.fire( "bar" );callbacks.remove( fn2 );callbacks.fire( "foobar" );/*output: foo*/

$.Callbacks( 'memory' ):

var callbacks = $.Callbacks( "memory" );callbacks.add( fn1 );callbacks.fire( "foo" );callbacks.add( fn2 );callbacks.fire( "bar" );callbacks.remove( fn2 );callbacks.fire( "foobar" );/*output:foofn2 says:foobarfn2 says:barfoobar*/

$.Callbacks( 'unique' ):

var callbacks = $.Callbacks( "unique" );callbacks.add( fn1 );callbacks.fire( "foo" );callbacks.add( fn1 ); // repeat additioncallbacks.add( fn2 );callbacks.fire( "bar" );callbacks.remove( fn2 );callbacks.fire( "foobar" );/*output:foobarfn2 says:barfoobar*/

$.Callbacks( 'stopOnFalse' ):

function fn1( value ){    console.log( value );    return false;}function fn2( value ){    fn1("fn2 says:" + value);    return false;}var callbacks = $.Callbacks( "stopOnFalse");callbacks.add( fn1 );callbacks.fire( "foo" );callbacks.add( fn2 );callbacks.fire( "bar" );callbacks.remove( fn2 );callbacks.fire( "foobar" );/*output:foobarfoobar*/

由于 $.Callbacks() 可以同时使用多个标识,因此,设置多个标识时,有累积的效果,相当于 "&&"。这意味着,在创建回调函数列表时,可以使用组合标识,例如,同时使用 unique 和 memory$.Callbacks("unique memory")),既保证回调函数列表中函数的唯一性,也可以保证在执行完函数后再添加的函数被调用时,可以使用上次调用时使用的参数。

$.Callbacks( 'unique memory' ):

function fn1( value ){    console.log( value );    return false;}function fn2( value ){    fn1("fn2 says:" + value);    return false;}    var callbacks = $.Callbacks( "unique memory" );callbacks.add( fn1 );callbacks.fire( "foo" );callbacks.add( fn1 ); // repeat additioncallbacks.add( fn2 );callbacks.fire( "bar" );callbacks.add( fn2 );callbacks.fire( "baz" );callbacks.remove( fn2 );callbacks.fire( "foobar" );/*output:foofn2 says:foobarfn2 says:barbazfn2 says:bazfoobar*/

jQuery 在延迟对象的 .done() 和 .fail() 中应用 $.Callbacks() 时也使用了标识组合,同时使用了 $.Callbacks('memory once')

$.Callbacks 方法同样可以被分离出来,这样就可以很方便的创建简单的别名:

var callbacks = $.Callbacks(),    add = callbacks.add,    remove = callbacks.remove,    fire = callbacks.fire;add( fn1 );fire( "hello world");remove( fn1 );

$.Callbacks, $.Deferred 和 Pub/Sub(观察者模式)

pub/sub (观察者模式) 的背后,总的想法是在应用程序中增强松耦合性。并非是在其它对象的方法上的单个对象调用。一个对象作为特定任务或是另一对象的活动的观察者,并且在这个任务或活动发生时,通知观察者。观察者也被叫作订阅者(Subscriber),它指向被观察的对象,既被观察者(Publisher 或 subject)。当事件发生时,被观察者(Publisher)就会通知观察者(subscriber)

作为 $.Callbacks() 的创建组件的一个演示,只使用回调函数列表,就可以实现 Pub/Sub 系统。将 $.Callbacks 作为一个文章队列,可以向下面这样,实现文章的发布和订阅:

var topics = {};jQuery.Topic = function( id ) {    var callbacks,        method,        topic = id && topics[ id ];    if ( !topic ) {        callbacks = jQuery.Callbacks();        topic = {            publish: callbacks.fire,            subscribe: callbacks.add,            unsubscribe: callbacks.remove        };        if ( id ) {            topics[ id ] = topic;        }    }    return topic;};

下面的代码可以作为你应用程序的一部分,可以相当简单的完成对感兴趣的文章的发布和订阅事件:

// Subscribers$.Topic( "mailArrived" ).subscribe( fn1 );$.Topic( "mailArrived" ).subscribe( fn2 );$.Topic( "mailSent" ).subscribe( fn1 );// Publisher$.Topic( "mailArrived" ).publish( "hello world!" );$.Topic( "mailSent" ).publish( "woo! mail!" );// Here, "hello world!" gets pushed to fn1 and fn2// when the "mailArrived" notification is published// with "woo! mail!" also being pushed to fn1 when// the "mailSent" notification is published. /*output:hello world!fn2 says: hello world!woo! mail!*/

尽管上面的代码很有用,但是可以进一步改进其实现。使用 $.Deferreds,可以保证当特定的任务被完成(或被解决)时,发布者只能向订阅者发布通知。参见下面的示例代码,进一步讨论如何在实践中使用这种情况:

// subscribe to the mailArrived notification$.Topic( "mailArrived" ).subscribe( fn1 );// create a new instance of Deferredsvar dfd = $.Deferred();// define a new topic (without directly publishing)var topic = $.Topic( "mailArrived" );// when the deferred has been resolved, publish a // notification to subscribersdfd.done( topic.publish );// Here the Deferred is being resolved with a message// that will be passed back to subscribers. It's possible to// easily integrate this into a more complex routine// (eg. waiting on an ajax call to complete) so that// messages are only published once the task has actually// finished.dfd.resolve( "its been published!" );
原创粉丝点击