803e31f6ddf2cd35ae57ef7b69214ea9.ppt
- Количество слайдов: 55
j. Query: New Features and APIs 4 -25 -2012
Contents • • • Introduction Deferred The New Event API © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 2
Introduction © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 3
Bio Rob Larsen has more than 12 years’ experience as a front end engineer and team leader, building web sites and applications for some of the world’s biggest brands. He is currently a Senior Specialist, Platform at Sapient Global Markets. Rob is an active writer and speaker on web technology with a special focus on emerging standards like HTML 5, CSS 3 and the ongoing evolution of Java. Script. He’s written one book, Professional j. Query (WROX), and is working on two more. github: github. com/roblarsen. Twitter: @robreact Blog @ HTML + CSS + Java. Script http: //htmlcssjavascript. com/ © COPYRIGHT 2012 SAPIENT CORPORATION | CONFIDENTIAL 4
Before we get started © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 5
Yes. I wrote (half of) this book. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 6
But… No. I’m not a complete j. Query fanboy. • http: //keithnorm-jschi. heroku. com/#4 © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 7
That guy works at Groupon, btw • He could probably buy John outright © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 8
#dumbjquerystuff • I don’t always agree with what they do. And this isn’t just API nitpicks o Killing $. tmpl() without a completed replacement o Killing the entire plugin site without a replacement in place © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 9
I’m Still Skeptical • • I was basically forced into using it every day only a couple of years ago Stylistically, there are things I dislike about j. Query o Everything is an anonymous function. • • • No code reuse Tightly coupled application logic Monolithic callbacks o I don’t believe less code or less characters always === better code • Sometimes it’s great, but, not always. o A prime example is the $(function(){}) shortcut for $(document). ready(function(){}) One is clear, especially for beginners. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 10
Still, The New Stuff is Shiny. • • And New. Based on the code I see day-to-day, “new” is roughly defined as 1. 5+ A couple of these are major and will make you better at your job Let’s look at what “new” means © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 11
Significant New Features of j. Query 1. 5+ • • 1. 5 o Rewrite of $. ajax() o Introduction of $. deferred() 1. 6 o attr() (use for actual HTML attributes) and prop() (use for DOM properties) • • This broke stuff o $. hold. Ready( ) • Manage the $. ready() event manually. 1. 7 o $. on() and $. off() • The one Event API to rule them all. o inner. Shivized versions of $. html(), etc. • HTML 5 magic © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 12
Two Stand Out (For Me, At Least) • Let’s look at some of this stuff in depth © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 13
Advanced Asynchronous Programming with j. Query Deferred © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 14
Defined • • • $. Deferred, introduced in version 1. 5, is a chainable utility object that provides fine-tuned control over the way callback functions are handled. For example, instead of merely having a single success method for your $. ajax calls, you can now define multiple callbacks that can be combined with precision and flexibility. No more: o Monolithic success blocks success : function(){ //10, 000 lines later } o Unmaintainable function calls buried at the end of other function calls success : function(){ //10, 000 lines later do. Something. Else(); } © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 15
Promises/Promises • • Basically defined, a promise is a proxy for the result of an action that will happen at an unspecified time in the future. j. Query’s specific implementation is based on the Promises/A proposal from Common. JS. var promise = ajax. Promise() { //XHR request //state is set to fulfilled, unfulfilled, or failed //depending on the result of the request return state }; function unfulfilled(){ //handle negative result } function fulfilled() { //handle successful result } fucntion failed(){ //Error! } promise. then( unfulfilled, failed ); © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 16
$. Deferred() • • j. Query’s implementation adds several useful enhancements. o Importantly, it integrates directly with $. ajax The format of the implementation is heavy on the ability to chain methods o It’s also written in a friendly, human-readable style. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 17
$. when, Deferred. done, and Deferred. fail • • • $. when accepts either one or more Deferred objects (which importantly include $. ajax calls) or a plain object. o If a Deferred is passed to $. when, its promise object is returned by the method. Deferred. done accepts a single function or array of functions to fire when a promise is resolved successfully. Deferred. fail also accepts a function or array of functions. It fires when a promise is rejected. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 18
$. when, Deferred. done, and Deferred. fail function fib() { return $. Deferred(function() { var int 1 = 0, int 2 = 1, int 3, sequence = "
So? • Although this is a simple example, it illustrates the power of the Deferred pattern. Callbacks in j. Query are a common source of tight coupling. They’re often defined in place, as anonymous functions with too little attention paid to abstraction. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 20
Decoupling for fun and profit • Without Deferreds, callback logic for animations is tied directly to the animation call as an optional complete argument. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 21
"), $statusbar = $("#statusbar"), html" src="https://present5.com/presentation/803e31f6ddf2cd35ae57ef7b69214ea9/image-22.jpg" alt="Traditionally… function update. Status() { var $update = $("
Decoupling for fun and profit • • • Though there’s a simple console. log in the complete argument in this example, far more complicated application data is commonly packed into similar complete callbacks. o This might be acceptable if update. Status will only ever be used with the anonymous callback function. Alternatively, to solve this, you could add a callback function as an argument to update. Status, but using Deferred and returning a resolved promise is far more flexible. The following code sample shows how update. Status could be rewritten to leverage Deferreds: © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 23
Rewritten Using Deferred function update. Status() { return $. Deferred(function() { var $update = $("
Decoupling for fun and profit • • With just the simple application of a Deferred, update. Status is now much more flexible. o Instead of being tied to a single callback, you can now use that same piece of code in several different flows. The following example contains three callback functions. o The first is equivalent to the original anonymous function in the original example. o The second, alternative. Callback, represents a different path to follow after the animation completes. • If the same animation is running on a second page, a different piece of markup will have to be updated. o The third, happy. Birthday, represents a function to be called in a special case where a specific UI update would be required, a “HAPPY BIRTHDAY” message indicator, for example. o Three uses of $. when follow. The first replicates the original case with a single callback function. The second shows the alternative callback. The third shows multiple callbacks. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 25
Profit! function callback(){ console. log("The animation is done. On to the next operation"); } function alternative. Callback(){ console. log("The animation is done. Let's follow a different path. "); } function special. Case(){ console. log("This is a special case. Let's do a special UI update. "); } $. when( update. Status() ) . done( callback ); //an alternative callback $. when( update. Status() ) . done( alternative. Callback ); //multiple callbacks $. when( update. Status() ) . done( [ callback, special. Case ] ); http: //jsfiddle. net/robreact/MFU 29/1/ © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 26
Decoupling for fun and profit • • As you can see, the code nicely decoupled the callback logic from the animation buried in the function body. No one even needs to read update. Status to know how the application flows. It’s all laid out in (nearly) plain English. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 27
Deferred. then, Syntactic Sugar for Deferred. fail() and Deferred. done • • • As with aliases for $. ajax like $. get and $. post, j. Query provides a convenient alias for the core Deferred objects: Deferred. then accepts two arguments, one for resolved promises and the other for rejected promises. Like the functions it maps to, Deferred. done and Deferred. fail, the arguments for Deferred. then can either be individual functions or an array of functions. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 28
$. Deferred. then() function fib() { return $. Deferred(function() { var int 1 = 0, int 2 = 1, int 3, sequence = "
Using the Deferred Aspects of $. ajax • • As was previously mentioned, $. ajax is a Deferred object the success, error, and complete callback methods are analogous to Deferred. done, Deferred. fail, and Deferred. always © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 30
A typical ajax request $. get("/status/json/", function( data ) { var $update = $( "
Using the Deferred Aspects of $. ajax • • Let’s leverage Deferred the arguments passed to update. Status are the same that would be passed to the callback function of a typical Ajax request. o the data, o a text string indicating request status o the j. Query XMLHttp. Request, (jq. XHR) object • an enhanced version of the standard XMLHttp. Request object. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 32
A Deferred ajax request function get. Status() { return $. ajax({ url : "/status/json/", data. Type : “json” }) } function update. Status( data ) { var $update = $( "
Using the Deferred Aspects of $. ajax • • note that once again the callback logic is decoupled from a single Ajax request get. Status function becomes more flexible multiple $. ajax requests can be passed into $. when multiple callbacks can be chained © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 34
Execute a Function No Matter What the Promise Resolution Is with Deferred. always • • • Oftentimes you want a function to be called no matter what the promise resolution is. use Deferred. always (this is just like the complete callback) The following code shows a simplified example that changes the “last updated” indicator in a mail application. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 37
Always! $. when( $. ajax( "/get/mail/" ) ). done( new. Messages, update. Message. List, update. Unread. Indicator ). fail( no. Messages ). always( function() { var date = new Date(); $( "#last. Updated" ). html( "Folder Updated: " + date. to. Date. String() + " at " + date. to. Time. String() ); } ); http: //jsfiddle. net/Seg. WH/ © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 38
Chaining and Filtering Deferreds with Deferred. pipe • • • Deferred. pipe, introduced in j. Query 1. 6, provides a method to filter and further chain Deferreds. The following code shows a simplified example that uses a chained animation used to manage the build out of the components of a web application. Once the animation queue is complete, the promise is automatically resolved and the done method is fired. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 39
Deferred. pipe function buildpage() { return $. Deferred(function( dfd ) { dfd. pipe(function() { return $( 'header' ). fade. In(); }) . pipe(function() { return $( '#main' ). fade. In(); }) . pipe(function() { return $( 'footer' ). fade. In(); }) }). resolve(); } $. when( buildpage() ) . done(function() { console. log(‘done’) } ); http: //jsfiddle. net/robreact/MQyq. Y/ © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 40
Filtering Deferreds with Deferred. pipe • • • Deferred. pipe can filter Deferreds based on secondary criteria. Deferred. pipe accepts three arguments: a done. Filter, a fail. Filter, and a progress. Filter Typical use case is a service that returns 200 with an empty result set. It will never get to the error callback. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 41
Deferred. pipe $. when( $. ajax( "/get/mail/" ) ). pipe( function( data ) { if ( data. messages. length > 0 ) { return data } else { return $. Deferred(). reject(); } } ). done( new. Messages, update. Message. List, update. Unread. Indicator ). fail( no. Messages ). always( function() { var date = new Date(); $("#last. Updated"). html("Folder Updated: " + date. to. Date. String() + " at " + date. to. Time. String() ); } ); © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 42
Resolving and Rejecting Promises • You occasionally need to manually resolve or reject promises. o Deferred. resolve and Deferred. reject. o optional args argument • • passed to the Deferred. done or Deferred. fail methods depending on the resolution of the promise The following example shows a simplified illustration of these optional arguments. Returning to the mail example, the code snippet creates an updated date string to represent the time of the mail update. This string is passed along to the Deferred. fail and Deferred. done methods. Additionally, the number of messages is passed to Deferred. done to update the #message paragraph with the current number of new messages retrieved. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 43
Reject and Resolve Manually function new. Messages( obj ) { $( "#message" ). text("you updated at " + obj. date + " and have " + obj. number + " new messages" ) } function no. Messages( obj ) { $( "#message" ). text("you updated at " + obj. date + " and have no new messages" ) } $. when( $. ajax( "/get/mail/" ) ). pipe( function( data ) { var date = new Date(); date = date. to. Date. String() + " at " + date. to. Time. String(); if ( data. messages. length > 0 ) { return $. Deferred(). resolve({ date: date, number: data. messages. length }); } else { return $. Deferred(). reject({ date: date }); } } ). done( new. Messages ). fail( no. Messages ); http: //jsfiddle. net/Vr. Lah/ © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 44
The new event API Clearing up a big, confusing mess © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 49
JQuery’s New Event API • • • Starting with version 1. 7 j. Query has made an effort to simplify the API for setting events. While you’ll still be able to. bind() and. unbind(), . live() and. die() and set. click() and. blur() the old way, there’s now a unified API which bundles all the various functionalities under one, consistent API. The two new methods are. on() and. off(). Moving forward these two new methods represent the preferred API The beauty of. on() is that it replaces the functionality of all the existing event methods with a single, flexible API The following code sample shows a basic example of. on(), using it to bind a click event to an element already present in the DOM. o This would compare to directly using. bind(“click”) or. click() © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 50
Basic $. on()
JQuery’s New Event API • • Beyond that basic example, on() also exposes the same functionality present in. delegate() and . live() and does so with the exact same syntax as the basic on() example. To use. on() like delegate() or. live(), simply add a second, optional selector argument representing the target element for the event. Here on() is used to listen for clicks on the document and fire the provided handler function if the click originates from an element with the id #anchor. Since the listener is set on the document, it will work whenever and wherever the #anchor appears. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 52
$. on() as $. live()
JQuery’s New Event API • • • Using on() like delegate() uses the exact same syntax as the live() replacement in the previous example. This illustrates one of the benefits of the new, simplified events API. o Instead of remembering two separate methods and their associated arguments, you simply remember the on() method and adjust your arguments accordingly. o If you truly need to bind events to generic elements across the whole page, you just use. on() on the document and pass in your generic p or a selector. o If, you want to follow the more performant delegate pattern, you simply apply. on() to a more focused selector © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 54
$. on() as $. delegate()
Hit Me!
JQuery’s New Event API • • Removing events is as simple as reversing the process with. off(), the same way you would use . unbind() or. die() The following code shows how to remove the events set in the previous examples. $( "#delegate“ ). off( "click", "p“ ); $( document ). off( "click", "#anchor“ ); $( "#a. Div“ ). off( 'click‘ ); © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 56
JQuery’s New Event API • As you can see, this new event API radically simplifies the way j. Query handles events. All the same power and convenience is still available, it’s just presented in a more straightforward, consistent manner. © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 57
One more thing © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 58
Open Source Stuff • • • I work on some open source projects. You can too. @h 5 bp o o o https: //github. com/h 5 bp/html 5 -boilerplate Build Scripts https: //github. com/h 5 bp/ant-build-script https: //github. com/h 5 bp/node-build-script (using grunt, more local flavor) https: //github. com/h 5 bp/rake-build-script @roblarsen o https: //github. com/roblarsen/Canvas. JS © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 59
Bio Rob Larsen github: http: //github. com/roblarsen Twitter: @robreact Blog @ HTML + CSS + Java. Script http: //htmlcssjavascript. com/ Come Work With Me: http: //bit. ly/IKSP 5 i © COPYRIGHT 2012 SAPIENT CORPORATION | CONFIDENTIAL 60
Thank You! © COPYRIGHT 2011 SAPIENT CORPORATION | CONFIDENTIAL 61


