jquery 1.7's callbacks feature demystified
jquery 1.7's callbacks feature demystified
function fn1(val) { console.log('f1 says: ' + val); } function fn2(val) { console.log('f2 says: ' + val) } var callbacks = $.Callbacks(); callbacks.add(fn1); callbacks.fire('foo!'); // output: f1 says foo! callbacks.add(fn2); callbacks.fire('bar!'); // output: // f1 says: bar! // f2 says: bar!flags: "once" – ensure the callback list can only be called once (整個list的funtion只會被執行一次, 後來加進來的也不會執行) "memory" – ensure if the list was already fired, adding more callbacks will have it called with the latest fired value 新加入的 function 先執行已經fire的event, list 裡面的 funtion 再執行 "unique" – ensure a callback can only be added to the list once "stopOnFalse" – interrupt callings when a particular callback returns false flags - once:var callbacks = $.Callbacks("once"); callbacks.add(fn1); callbacks.fire('foo'); callbacks.add(fn2); callbacks.fire('bar'); callbacks.remove(fn2); callbacks.fire('foobar'); // ouput: // fooflags - memory:var callbacks = $.Callbacks('memory'); callbacks.add(fn1); callbacks.fire('foo'); callbacks.add(fn2); callbacks.fire(''bar''); callbacks.remove(fn2); callbacks.fire('foobar'); /* fn1 says: foo <- first fire fn2 says: foo <- second fire. 新加入的 fn2 先執行已經fire的event, list 裡面的 funtion 再執行 fn1 says: bar fn2 says: bar fn1 says: foobar <- third fire */flags - unique:var callbacks = $.Callbacks('unique'); callbacks.add(fn1); callbacks.fire('foo); callbacks.add(fn1); // repeat addition callbacks.add(fn2); callbacks.fire('bar'); callbacks.remove(fn2); callbacks.fire('foobar'); /* fn1 says: foo <- first fire fn1 says: bar <- second fire fn2 says: bar fn1 says: foobar <- third fire */flags - stopOnFalse:function fn1(val) { console.log('f1 says: ' + val); return false; } function fn2(val) { console.log('f2 says: ' + val) return false; } var callbacks = $.Callbacks('stopOnFalse'); callbacks.add(fn1); callbacks.fire('foo'); callbacks.add(fn2); callbacks.fire('bar'); callbacks.remove(fn2); callbacks.fire('foobar'); /* fn1 says: foo <- first fire fn1 says: bar <- second fire fn1 says: foobar <- third fire */Flag combinations are internally used with $.Callbacks in jQuery for the .done() and .fail() buckets on a Deferred – both of which use "memory once". pub/sub implementationvar 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! */Whilst this is great, we can take this pub/sub implementation further. Using $.Deferreds, we can ensure that publishers only publish notifications for subscribers once particular tasks have been completed (resolved). See the below code sample for some further comments on how this could be used in practice:// subscribe to the mailArrived notification $.Topic( 'mailArrived' ).subscribe( fn1 ); // create a new instance of Deferreds var dfd = $.Deferred(); // define a new topic (without directly publishing) var topic = $.Topic( 'mailArrived' ); // when the deferred has been resolved, we'll // then publish a notification to subscribers dfd.done( topic.publish ); // here we're resolving the Deferred with a message // that will be passed back to subscribers. We could // easily integrate this into a more complex routine // (eg. waiting on an ajax call to complete) so that // we only published once the task finished. dfd.resolve( 'its been published!' );
沒有留言:
張貼留言