Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dealing with asynchronous JavaScript: Events, Callbacks & Promises/Deferreds

Lee Boonstra
September 07, 2015

Dealing with asynchronous JavaScript: Events, Callbacks & Promises/Deferreds

In real-world applications, we often deal with asynchronous code, for example to retrieve data from various systems. In this session, Lee Boonstra will talk about the various ways on how to deal with asynchronous bit of code. A talk about Events, Callbacks and the new Ext JS 6 Promises.

Lee Boonstra

September 07, 2015
Tweet

More Decks by Lee Boonstra

Other Decks in Technology

Transcript

  1. Asynchronous JavaScript:
    Events, Callbacks & Promises
    Lee Boonstra
    @ladysign

    View Slide

  2. Which value will be alerted?
    var  i  =  5;  
    function  calc(num){  
    setTimeout(function(){    
    i  =  i  *  0;    
    return  i;  
    },  3000);                                      
    i  =  i  *  5;  
    }  
    calc(5);  
    alert(i);
    Answer?
    A) 5
    B) 25
    C) 0

    View Slide

  3. JavaScript is Single Threaded
    • Code executes from top to bottom
    • Right after each other
    • 2 bits of code cannot run at the same time

    View Slide

  4. The Event Loop
    • Queue of callback functions
    • JS engine won’t start
    processing after the code after
    the method has been executed

    View Slide

  5. So, how to deal with async code?
    • Events
    • Callbacks
    • Promises

    View Slide

  6. Events

    View Slide

  7. Observer Pattern
    • Events are a solution to communicate when
    async callbacks finish executing.
    • Objects can publish events that other
    objects can listen for.
    • Ext.mixin.Observable

    View Slide

  8. Types of events
    • User Events
    • System Events
    • Life Cycle Events
    button.addListener('tap',          
    function(c)  {  
           //do  something  
    });
    User Event
    store.on('load',  
    function(store)  {  
           //do  something  
    });
    System Event
    grid.on('afterrender',  
    function(c)  {  
         //do  something  
    });
    Life Cycle Event

    View Slide

  9. View
    ViewController
    Ext.define(‘MyApp.view.MyViewController’,  
    extend:  ‘Ext.app.ViewController’,  
    alias:  'controller.myviewcontroller',  
    onAfterRender:  function(){  
    //do  something…  
    }  

    ..  
    controller:  ‘myviewcontroller’,  
    listeners:  {  
      ‘tap’  :  ‘onButtonTap’,    
      ‘afterrender':‘onAfterRender’  
    }  
    MVVM Listeners

    View Slide

  10. “Events are great for things that can happen multiple
    times on the same object.
    With those events you don't really care about what
    happened before you attached the listener.
    But when it comes to asynchronous methods which
    have on success or on failure behavior, you rather
    want to use callbacks.”

    View Slide

  11. Callbacks

    View Slide

  12. Callback
    • Commonly used in asynchronous operations
    • When you call a function, pass in another
    function as argument

    View Slide

  13. Example VC

    View Slide

  14. Example
    Ext.Ajax.request({  
             url:  'feed.json',  
             success:  function(response,  opts)  {  
                   //doSomething()  
             },  
             failure:  function(response,  opts)  {  
                   //doSomething()  
             }  
     });

    View Slide

  15. Example
    mystore.sync({  
    success:  function(batch,  o){  },  
    failure:  function(batch,  o){  },  
    callback:  function(batch,  o){  }  
    });

    View Slide

  16. Tip!
    • Always use a loading spinner before you
    make your asynchronous call.
    • Never forget to clear the spinner, on success
    and failure.

    View Slide

  17. View Slide

  18. Actor
    MainController
    user clicks play
    request selection from grid
    Grid SpotifyManager
    check if artist, track or album
    execute spotify
    return record
    make JsonP request
    play song / display error

    View Slide

  19. Example VC
    //app/view/main/MainController.js  
    onPlay:  function(){  
     var  s  =  me.getViewModel().get(‘mygrid’).selection;  
     var  rec  =  s.getData();  
    //spinner  
     Engine.manager.Spotify.execSpotify(rec,  doneFnSpotify);  
    }

    View Slide

  20. Callback horror
    • Unmaintainable / unreadable code due too
    many nested callbacks.
    • This is where JavaScript promises might
    become handy!

    View Slide

  21. Promises

    View Slide

  22. Promise
    • represents a “contract” for a value not
    securely known when the promise is created
    • an object or function with a “then” method
    whose behavior conforms to this
    specification.
    • A Promise can only succeed or fail once.

    View Slide

  23. Promise states
    • fulfilled - the action relating to the promise succeeded
    • rejected - the action relating to the promise failed
    • pending - hasn't fulfilled or rejected yet
    • settled - has fulfilled or rejected

    View Slide

  24. Thenable

    View Slide

  25. The Promises A+ Spec
    This specification details the behavior of the then method, providing an
    interoperable base which all Promises/A+ conformant promise implementations
    can be depended on to provide.

    https://github.com/promises-aplus/promises-spec

    Ext JS 6 & Web Application Manager Promises are conform this spec!

    View Slide

  26. An example of a Promise in JavaScript (ECMAScript 6):
    var  p  =  new  Promise(function(resolve,  reject)  {  
       //do  something();  
       if  (/*  everything  turned  out  fine  */)  {  
           resolve("OK");  
       }  else  {  
           reject(Error("Oh  no!"));  
       }  
    });  

    View Slide

  27. How to use:
    p.then(function(result)  {  
       console.log(result);  //  "OK"  
    },  function(err)  {  
       console.log(err);  //  Error:  "Oh  no!"  
    });

    View Slide

  28. Real world example

    View Slide

  29. example of a callback, later I will rewrite it to use a promise
    var  done  =  function(err,  jobs){  
    res.render("myview",  {    
     user  :  req.user,  
         jobs:  jobs  
     });  
    };  
    getJobs  =  function(req,  done){  
        Job.findJobsOfUser(req.user._id,  function(err,  jobs){  
          if(err)  throw  err;  
          done(null,  jobs);  
        });  
    }  
    var  jobs  =  getJobs(req,  done);  
    This becomes callback horror, when I want to load more things, before rendering the page.

    View Slide

  30. My solution, with the use of Promises…
    getJobs(req).then(function(jobs){  
           if(jobs){  
              //now  if  I  want  to  chain  this  with  more  calls  
              //i  just  run  the  res.render  call  last  (or  finally)  
             res.render("profile",  {    
                 user  :  req.user,  
                 jobs:  jobs  
             });  
           }  
    },  function(error){  
           throw  error;  
    });

    View Slide

  31. How to use:
    function  getJobs(req){  
        var  promise  =  new  Promise(function  (resolve,  reject)  {  
           Job.findJobsOfUser(req.user._id,  function  (err,  jobs)  {  
               if  (err)  reject(err);  
               else  resolve(jobs);  
           });  
        });  
         
        return  promise;  
    }

    View Slide

  32. Browser Support

    View Slide

  33. Promises in Ext JS
    • Ext JS 6 conforms Promises/A spec
    • Ext.Ajax is thenable.
    • Two forms: Ext.Promise() & Ext.Deferred()
    • Ext.Promise() - ECS6 wrapper
    • Ext.Deferred() - extra enhancements

    View Slide

  34. Example Ext.Promise
           requestUserName:  function(){  
              var  s  =  this.getStore();  
              return  new  Ext.Promise(function  (resolve,  reject)  {  
                s.load({  
            callback:  function(records,  operation,  success)  {  
                         if(success){  
                           if(records.length  >  0){  
                              resolve(records);  
                           }  else  {  
                              resolve(false);  
                           }  
                         }  else{  
                           reject(operation);  
                         }  
                 }  
          });  
              });  
           }

    View Slide

  35. Use Ext.Promise
    this.requestUserName().then(function(records){  
       if(records){  
           //do  something  
       }  
    },  function(error){  
       //throw  error  
    });

    View Slide

  36. API methods
    • Promise.resolve(promiseOrAThenableValue)
    • Promise.reject(reason)
    • Promise.all(arrPromisesOrAThenableValues)

    View Slide

  37. Instance methods
    • p.then(onFulfilled, onRejected, onProgress)
    • p.done()
    • p.cancel(reason)
    • p.always(onCompleted)
    • p.otherwise(onRejected)

    View Slide

  38. Ext.Ajax built-in Promises
    Ext.Ajax.request({  
           url:  'feed.json',  
    }).then(function  (response)  {  
           //  use  response  
    });  
    //Ext.Ajax  extends  from  Ext.data.request.Base  

    View Slide

  39. Ext.Ajax.request({  
           url:  'feed.json',  
    }).then(function(response)  {  
           //  use  response  
    }).always(function()  {  
         //  clean-­‐up  logic,  regardless  the  outcome  
    }).otherwise(function(reason){  
         //  handle  failure  
    });

    View Slide

  40. Promises in Web Application Manager
    • Invoke API (to invoke other applications)
    • Device Camera API
    • Download Files API
    • File Collections & Secure Files APIs
    • Secure LocalStorage API
    • …

    View Slide

  41. Actor
    SETTINGS
    user clicks username save
    request username from localstorage
    LOCAL STORAGE LASTFM MANAGER
    return results to the user
    request lastfm playlist
    return result
    if no records exist, add new, else edit
    return username

    View Slide

  42. View Slide

  43. Deferreds

    View Slide

  44. Deferreds
    • mechanism used to create new Promises
    with Ext JS 6
    • Promises with additional features

    View Slide

  45. Ext.Deferred
    doSomething:  function  ()  {  
             var  d  =  new  Ext.Deferred();  //create  the  Ext.Deferred  object  
             mystore.load({  
                     callback:  function  (records,  operation,  success)  {  
                             if  (success)  {  
                                     //  Use  "deferred"  to  drive  the  promise:  
                                     d.resolve(records);  
                             }  
                             else  {  
                                     //  Use  "deferred"  to  drive  the  promise:  
                                     d.reject("Error  loading  data.");  
                             }  
                     }  
             });  
             return  d.promise;    //  return  the  Promise  to  the  caller  
     }

    View Slide

  46. Conclusion

    View Slide

  47. Async JavaScript
    Events
    • Observer Pattern. Users, System and the
    LifeCycle can throw events, which are
    asynchronous. - There is no success or
    failure.

    View Slide

  48. Async JavaScript
    Callbacks
    • Asynchronous JS. You pass a function in a
    function, deal with on success or failure.

    View Slide

  49. Async JavaScript
    Promises
    • The result of a task, which can be fulfilled
    or rejected. Promises are chain-able.

    View Slide

  50. Async JavaScript
    Ext.Deferred
    • Like Promises, but can be used as a base
    class, to let your methods return promises.
    • Sencha deferreds give additional extras

    View Slide

  51. Resources
    • http://docs.sencha.com/extjs/6.0/6.0.0-classic/#!/api/Ext.Promise
    • http://docs.sencha.com/extjs/6.0/6.0.0-classic/#!/api/Ext.promise.Promise-method-then
    • http://docs.sencha.com/extjs/6.0/6.0.0-classic/#!/api/Ext.Deferred
    • https://github.com/promises-aplus/promises-spec
    • https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise

    View Slide

  52. Questions?

    View Slide