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

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

8a235da15adae86851fa3216834198ed?s=47 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.

8a235da15adae86851fa3216834198ed?s=128

Lee Boonstra

September 07, 2015
Tweet

Transcript

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

  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
  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
  4. The Event Loop • Queue of callback functions • JS

    engine won’t start processing after the code after the method has been executed
  5. So, how to deal with async code? • Events •

    Callbacks • Promises
  6. Events

  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
  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
  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
  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.”
  11. Callbacks

  12. Callback • Commonly used in asynchronous operations • When you

    call a function, pass in another function as argument
  13. Example VC

  14. Example Ext.Ajax.request({            url:  'feed.json',  

             success:  function(response,  opts)  {                  //doSomething()            },            failure:  function(response,  opts)  {                  //doSomething()            }    });
  15. Example mystore.sync({   success:  function(batch,  o){  },   failure:  function(batch,

     o){  },   callback:  function(batch,  o){  }   });
  16. Tip! • Always use a loading spinner before you make

    your asynchronous call. • Never forget to clear the spinner, on success and failure.
  17. None
  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
  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);   }
  20. Callback horror • Unmaintainable / unreadable code due too many

    nested callbacks. • This is where JavaScript promises might become handy!
  21. Promises

  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.
  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
  24. Thenable

  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!
  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!"));      }   });  
  27. How to use: p.then(function(result)  {      console.log(result);  //  "OK"

      },  function(err)  {      console.log(err);  //  Error:  "Oh  no!"   });
  28. Real world example

  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.
  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;   });
  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;   }
  32. Browser Support

  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
  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);                        }                }         });             });          }
  35. Use Ext.Promise this.requestUserName().then(function(records){      if(records){        

     //do  something      }   },  function(error){      //throw  error   });
  36. API methods • Promise.resolve(promiseOrAThenableValue) • Promise.reject(reason) • Promise.all(arrPromisesOrAThenableValues)

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

    • p.always(onCompleted) • p.otherwise(onRejected)
  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  
  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   });
  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 • …
  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
  42. None
  43. Deferreds

  44. Deferreds • mechanism used to create new Promises with Ext

    JS 6 • Promises with additional features
  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    }
  46. Conclusion

  47. Async JavaScript Events • Observer Pattern. Users, System and the

    LifeCycle can throw events, which are asynchronous. - There is no success or failure.
  48. Async JavaScript Callbacks • Asynchronous JS. You pass a function

    in a function, deal with on success or failure.
  49. Async JavaScript Promises • The result of a task, which

    can be fulfilled or rejected. Promises are chain-able.
  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
  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
  52. Questions?