KEMBAR78
Event driven javascript | PDF
Event Driven
           Javascript



federico.galassi@cleancode.it
slidehare.net/fgalassi
• Event driven programming
• History of javascript design
• Event driven javascript
Software
components
 exchange
information
Producers
    give
information
Consumers
    take
information
Taxonomy of
interaction models
Who is the
producer ?
Known
Where’s Kenny?


  Over There!
Unknown
Where’s Kenny?


  Over There!

                 Where’s Kenny?
Who is the
producer ?
known   unknown
How does
information flow ?
Pull
Where’s Kenny?


  Over There!
Push
  Let me know
 where’s Kenny

      Ok



... later ...
Hey! Over There!
How does
       information flow ?
         known    unknown
pull

push
4 Models of
interaction
1.
        known     unknown

        Request
pull
       Response


push
Request
        Response
//  method  invocation
weapon  =  armory.buy(“shuriken”)
kenny  =  cartman.findKenny()
kenny.kill(weapon)
Request
Response


       SIMPLE
Request
Response


       SIMPLE
      SEQUENTIAL
Request
Response


       SIMPLE
      SEQUENTIAL
      IMPERATIVE
Request
Response

HUMAN
Request
      Response

 TIGHT
COUPLING
            SEQUENTIAL
            IMPERATIVE
Request
        Response

 TIGHT
COUPLING

INEFFICIENT   SEQUENTIAL
              IMPERATIVE
2.
        known     unknown

                  Anonymous
        Request
pull                Request
       Response    Response


push
Anonymous
Request Response


  The system decouples
information and its owner
Anonymous
Request Response


  load balancer
Anonymous
          Request Response

alancer               FAILOVER
Anonymous
          Request Response

alancer               FAILOVER

                      EXTENSIBLE
Anonymous
  Request Response

  SYSTEM
COMPLEXITY
3.
        known     unknown

                  Anonymous
        Request
pull                Request
       Response    Response


push   Callback
Callback

//  observer  pattern
cartman.findKenny(
    function(kenny)  {
        kenny.kill(weapon)
})
Don’t call us
We’ll call you
From Sequential

            COMPUTATION

INPUT                     OUTPUT

              STATE
To State Machine
INPUT        STATE A
                  COMPUTATION



INPUT        STATE B
                  COMPUTATION



INPUT        STATE C            OUTPUT
Callback

Relinquish control
Callback
 Just in time is optimal

                      Producers



Consumer
Callback


       efficiency
Callback


EXPLICIT      efficiency
CONTROL
  FLOW
4.
        known      unknown

                   Anonymous
        Request
pull                 Request
       Response     Response


push   Callback   Event Driven
Callback +
   Anonymous
Request Response
        =
   EVENTS
Home Automation
   Example
EVENTS
 FAILOVER +       system
               COMPLEXITY +
EXTENSIBLE +
                 explicit
 efficiency = control flow =
-------------
------------
 ------------   -------------
                ------------
                 ------------
  power           chaos
Expressive Power
               EVENTS




                                ANON.
CALLBACK                       REQUEST
           REQUEST RESPONSE   RESPONSE
Complexity
Javascript
     is
event driven
Not
Javascript
   Fault
Not
Your
Fault
Just an
HARDER
problem
• Event driven programming
• History of javascript design
• Event driven javascript
In the old days...




            Netscape Headquarters
                   May 1995
This guy had two
   problems...



             Brendan Eich
          Creator of Javascript
1. The world is
  Concurrent
... and so is
   browser
User Input
Network Requests
2. Very very very
          short time




LiveScript first shipped in betas of Netscape Navigator 2.0 in
                       September 1995
Be
Pragmatic
He could use
Threads ...
  Real preemptive
   concurrency
Threads
  are
  Evil
He could use
Coroutines ...
  Emulated
 cooperative
 concurrency
needs a
complex
 scheduler
He was a
functional
   guy
Take it easy



Not concurrent
Just non-blocking
First class functions
//  callbacks  give
//  non  linear  execution
wally.takeJob(function  work()  ...)
wally.getCoffee(function  drink()  ...)


//  ...  later  ...
//  first  drink  coffee
//  then  work
Simple event loop
        //  make  it  look  concurrent
        button.onclick(function()  {
           div.style.color  =  “red”
        })

 UI                       UI update      Click handler



event     UI update      Click handler
queue    Click handler

time
         User click
Non-blocking I/O
//  network  async  api
xhr.onreadystatechange  =  function(){
 ...
})

//  DOM  in  memory
div.innerHTML  =  “Hello”
Javascript won
But
 sold its soul
for simplicity
One thread
     =
  Freeze
No Wait()
Simple sequential
function  breakfast()  {
   var  bacon  =  bacon()
   var  juice  =  orangeJuice()
   eat(bacon,  juice)
}                     computation


function  bacon()  {
   //  get  bacon
   return  bacon
}
Async gets in
function  breakfast()  {
   var  bacon  =  bacon() wrong
   var  juice  =  orangeJuice()
   eat(bacon,  juice)
}

function  bacon()  {
   getBacon(function(bacon)  {
       //  got  bacon
   })
   return what?
}
Break computation
function  breakfast()  {
      var  callback  =  function(bacon)  {
        var  juice  =  getOrangeJuice()
        eat(bacon,  juice)
     }                    rest of computation
     bacon(callback)
}            computation

function  bacon(callback)  {
   //  get  bacon  async
   callback(bacon)
}
Break more
function  breakfast()  {
      var  callback  =  function(bacon)  {
        var  callback  =  function(juice)  {
           eat(bacon,  juice) rest of computation 2
        }
        getOrangeJuice(callback)
     }                          rest of computation 1
     bacon(callback)
}            computation
Continuation
  Passing
   Style
it’s Viral         1


//  simple  sequential  computation

function  A()  {  return  B()  }
function  B()  {  return  C()  }
function  C()  {  return  value  }

A()
it’s Viral         2

//  C  becomes  async,  everything  becomes  async

function  A(callback)  {
  B(function(value)  {  callback(value)  })
}
function  B(callback)  {
  C(function(value)  {  callback(value)  })
}
function  C(callback)  {  callback(value)  }

A()
it’s Hard          sleep



//  simple  sequential  sleep

sleep(3000)
doSomething()
it’s Hard           sleep


//  not  so  simple  sleep

setTimeout(function()  {
   doSomething()
},  3000)
it’s Hard          loop



//  simple  sequential  loop

images.forEach(function(url)
  var  image  =  fetchImage(url)
  image.show()
}
it’s Hard      loop



//  fetchImage  is  async

images.forEach(function(url)
  fetchImage(url,  function(image)  {
     image.show()
  })
}
it’s Hard            loop

//  Show  them  in  the  right  order

function  processImage()  {
  var  url  =  images.shift()
  if  (url)  {
     fetchImage(url,  function(image)  {
        image.show()
        processImage()
     })
  }
}
processImage()
Javascript
  sacrificed
convenience
for simplicity
... and it was the
    right choice
• Event driven programming
• History of javascript design
• Event driven javascript
How can we
   tame
complexity?
Add
Wait()
stupid!
Easy        sleep

//  simple  sequential  sleep  with  wait/resume

sleep(3000)
doSomething()

function  sleep(msec)  {
  wait(
     setTimeout(function()  {
        resume()
     },  msec)
  )
}
Beautiful
Already done !
//  write  sequential  logic

function  doOpsABC()  {
   waitfor  {
      var  x  =  doOpA()
   }
   and  {
      var  y  =  doOpB()
   }
   return  doOpC(x,y)
}



   http://stratifiedjs.org/
Transform to
continuation
  passing
    style
//  synchronous  read

fs.read(path).wait()




     http://nodejs.org/
Implement
coroutines
Back to
complexity
Jeremy Ashkenas - CoffeeScript




         “Case in point, Stratified JS: A virtuoso performance of
         JavaScript compilation, but look at what it compiles into.”


         “I don't think we want to take CoffeeScript down that
         path. Open the Pandora's box of injecting special
         functions into the runtime, and ... suddenly you have to
         worry about being orders of magnitude slower than
         normal JS.”
   https://github.com/jashkenas/coffee-script/issuesearch?state=closed&q=asynchronous#issue/350/comment/330116
Jeremy Ashkenas - CoffeeScript




var getDocument = function(){   var getDocument;
   waitfor(document) {          __oni_rt.exec(__oni_rt.Seq(0,__oni_rt.Seq(0,__oni_rt.Nblock(
     resume(db.get(id));        function(arguments){
   }                              getDocument=function (){
   return document;                 return __oni_rt.exec(__oni_rt.Seq(1,__oni_rt.Suspend(
};                                  function(arguments, resume){
                                       return __oni_rt.exec(__oni_rt.Seq(0,__oni_rt.Fcall(0,__oni_rt.Nbl
                                       function(arguments){
                                          return resume;
                                       }),__oni_rt.Nblock(function(arguments){
                                          return db.get(id)
                                       })
                                    )),arguments,this)},
                                    function() {
                                       document=arguments[0];
                                    }),__oni_rt.Fcall(0,__oni_rt.Return,__oni_rt.Nblock(
                                    function(arguments){
                                       return document;
                                    })
                                  )),arguments, this)};
                                }))), this.arguments, this);
Ryan Dahl - node.js




      “I will be removing wait() in the next release of Node.
     It has already been removed from the documentation.”


     “A proper implementation of wait() necessitates true
     coroutines”

     “This sort of mental complication is exactly what I'm
     trying to avoid in Node.”


           http://groups.google.com/group/nodejs/msg/df199d233ff17efa
Take it easy



   No wait()
Just flow control
Sequence                  1

//  async  sequential  computation
sequence(get,  filter,  process)

function  get(resume)  {
  $.get(url,  function(data)  {
     resume(data)
  })
}

function  filter(resume,  data)  {  ...  }
function  process(resume,  data)  {  ...  }
Sequence              2

//  async  sequential  computation

function  sequence()  {
  var  steps  =  arguments.slice()
  var  doStep  =  function(val)  {
     var  next  =  steps.shift()
     if  (next)  {
        next.apply(null,  [doStep,  val])
     }
  }
  doStep()
}
Functional
      programming
first(fetchA,  fetchB,  fetchC)
every(checkA,  checkB,  checkC)
map(array,  mapper)
filter(array,  filter)
From imperative
var  clicks  =  0,  timeout  =  null

$(“button”).click(function()  {
    clicks++
    if  (clicks  ==  1)  {
         timeout  =  setTimeout(function()  {
             clicks  ==  0
         })
    }
    if  (clicks  ==  3)  {
         clearTimeout(timeout)
         clicks  =  0
         $(this).trigger(“tripleclick”)
    }
})
To declarative
$(button)
 .on(“click”)
 .times(3)
 .within(“1  second”)
 .trigger(“tripleclick”)
Questions?
federico.galassi@cleancode.it

Event driven javascript

  • 1.
    Event Driven Javascript federico.galassi@cleancode.it slidehare.net/fgalassi
  • 2.
    • Event drivenprogramming • History of javascript design • Event driven javascript
  • 3.
  • 4.
    Producers give information
  • 5.
    Consumers take information
  • 6.
  • 7.
  • 8.
  • 9.
    Unknown Where’s Kenny? Over There! Where’s Kenny?
  • 10.
    Who is the producer? known unknown
  • 11.
  • 12.
  • 13.
    Push Letme know where’s Kenny Ok ... later ... Hey! Over There!
  • 14.
    How does information flow ? known unknown pull push
  • 15.
  • 16.
    1. known unknown Request pull Response push
  • 17.
    Request Response //  method  invocation weapon  =  armory.buy(“shuriken”) kenny  =  cartman.findKenny() kenny.kill(weapon)
  • 18.
  • 19.
    Request Response SIMPLE SEQUENTIAL
  • 20.
    Request Response SIMPLE SEQUENTIAL IMPERATIVE
  • 21.
  • 22.
    Request Response TIGHT COUPLING SEQUENTIAL IMPERATIVE
  • 23.
    Request Response TIGHT COUPLING INEFFICIENT SEQUENTIAL IMPERATIVE
  • 24.
    2. known unknown Anonymous Request pull Request Response Response push
  • 25.
    Anonymous Request Response The system decouples information and its owner
  • 26.
  • 27.
    Anonymous Request Response alancer FAILOVER
  • 28.
    Anonymous Request Response alancer FAILOVER EXTENSIBLE
  • 29.
    Anonymous RequestResponse SYSTEM COMPLEXITY
  • 30.
    3. known unknown Anonymous Request pull Request Response Response push Callback
  • 31.
    Callback //  observer  pattern cartman.findKenny(    function(kenny)  {        kenny.kill(weapon) })
  • 32.
  • 33.
    From Sequential COMPUTATION INPUT OUTPUT STATE
  • 34.
    To State Machine INPUT STATE A COMPUTATION INPUT STATE B COMPUTATION INPUT STATE C OUTPUT
  • 35.
  • 36.
    Callback Just intime is optimal Producers Consumer
  • 37.
    Callback efficiency
  • 38.
    Callback EXPLICIT efficiency CONTROL FLOW
  • 39.
    4. known unknown Anonymous Request pull Request Response Response push Callback Event Driven
  • 40.
    Callback + Anonymous Request Response = EVENTS
  • 41.
  • 42.
    EVENTS FAILOVER + system COMPLEXITY + EXTENSIBLE + explicit efficiency = control flow = ------------- ------------ ------------ ------------- ------------ ------------ power chaos
  • 43.
    Expressive Power EVENTS ANON. CALLBACK REQUEST REQUEST RESPONSE RESPONSE
  • 44.
  • 45.
    Javascript is event driven
  • 46.
  • 47.
  • 48.
  • 49.
    • Event drivenprogramming • History of javascript design • Event driven javascript
  • 50.
    In the olddays... Netscape Headquarters May 1995
  • 51.
    This guy hadtwo problems... Brendan Eich Creator of Javascript
  • 52.
    1. The worldis Concurrent
  • 53.
    ... and sois browser
  • 54.
  • 55.
    2. Very veryvery short time LiveScript first shipped in betas of Netscape Navigator 2.0 in September 1995
  • 56.
  • 57.
    He could use Threads... Real preemptive concurrency
  • 58.
  • 59.
    He could use Coroutines... Emulated cooperative concurrency
  • 60.
  • 61.
  • 62.
    Take it easy Notconcurrent Just non-blocking
  • 63.
    First class functions // callbacks  give //  non  linear  execution wally.takeJob(function  work()  ...) wally.getCoffee(function  drink()  ...) //  ...  later  ... //  first  drink  coffee //  then  work
  • 64.
    Simple event loop //  make  it  look  concurrent button.onclick(function()  { div.style.color  =  “red” }) UI UI update Click handler event UI update Click handler queue Click handler time User click
  • 65.
    Non-blocking I/O //  network async  api xhr.onreadystatechange  =  function(){ ... }) //  DOM  in  memory div.innerHTML  =  “Hello”
  • 66.
  • 67.
    But sold itssoul for simplicity
  • 68.
    One thread = Freeze
  • 69.
  • 70.
    Simple sequential function  breakfast() { var  bacon  =  bacon() var  juice  =  orangeJuice() eat(bacon,  juice) } computation function  bacon()  { //  get  bacon return  bacon }
  • 71.
    Async gets in function breakfast()  { var  bacon  =  bacon() wrong var  juice  =  orangeJuice() eat(bacon,  juice) } function  bacon()  { getBacon(function(bacon)  { //  got  bacon }) return what? }
  • 72.
    Break computation function  breakfast() {      var  callback  =  function(bacon)  { var  juice  =  getOrangeJuice() eat(bacon,  juice) } rest of computation bacon(callback) } computation function  bacon(callback)  { //  get  bacon  async callback(bacon) }
  • 73.
    Break more function  breakfast() {      var  callback  =  function(bacon)  { var  callback  =  function(juice)  { eat(bacon,  juice) rest of computation 2 } getOrangeJuice(callback) } rest of computation 1 bacon(callback) } computation
  • 74.
  • 75.
    it’s Viral 1 //  simple  sequential  computation function  A()  {  return  B()  } function  B()  {  return  C()  } function  C()  {  return  value  } A()
  • 76.
    it’s Viral 2 //  C  becomes  async,  everything  becomes  async function  A(callback)  { B(function(value)  {  callback(value)  }) } function  B(callback)  { C(function(value)  {  callback(value)  }) } function  C(callback)  {  callback(value)  } A()
  • 77.
    it’s Hard sleep //  simple  sequential  sleep sleep(3000) doSomething()
  • 78.
    it’s Hard sleep //  not  so  simple  sleep setTimeout(function()  { doSomething() },  3000)
  • 79.
    it’s Hard loop //  simple  sequential  loop images.forEach(function(url) var  image  =  fetchImage(url) image.show() }
  • 80.
    it’s Hard loop //  fetchImage  is  async images.forEach(function(url) fetchImage(url,  function(image)  { image.show() }) }
  • 81.
    it’s Hard loop //  Show  them  in  the  right  order function  processImage()  { var  url  =  images.shift() if  (url)  { fetchImage(url,  function(image)  { image.show() processImage() }) } } processImage()
  • 82.
  • 83.
    ... and itwas the right choice
  • 84.
    • Event drivenprogramming • History of javascript design • Event driven javascript
  • 85.
    How can we tame complexity?
  • 86.
  • 87.
    Easy sleep //  simple  sequential  sleep  with  wait/resume sleep(3000) doSomething() function  sleep(msec)  { wait( setTimeout(function()  { resume() },  msec) ) }
  • 88.
  • 89.
  • 90.
    //  write  sequential logic function  doOpsABC()  { waitfor  { var  x  =  doOpA() } and  { var  y  =  doOpB() } return  doOpC(x,y) } http://stratifiedjs.org/
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
    Jeremy Ashkenas -CoffeeScript “Case in point, Stratified JS: A virtuoso performance of JavaScript compilation, but look at what it compiles into.” “I don't think we want to take CoffeeScript down that path. Open the Pandora's box of injecting special functions into the runtime, and ... suddenly you have to worry about being orders of magnitude slower than normal JS.” https://github.com/jashkenas/coffee-script/issuesearch?state=closed&q=asynchronous#issue/350/comment/330116
  • 96.
    Jeremy Ashkenas -CoffeeScript var getDocument = function(){ var getDocument; waitfor(document) { __oni_rt.exec(__oni_rt.Seq(0,__oni_rt.Seq(0,__oni_rt.Nblock( resume(db.get(id)); function(arguments){ } getDocument=function (){ return document; return __oni_rt.exec(__oni_rt.Seq(1,__oni_rt.Suspend( }; function(arguments, resume){ return __oni_rt.exec(__oni_rt.Seq(0,__oni_rt.Fcall(0,__oni_rt.Nbl function(arguments){ return resume; }),__oni_rt.Nblock(function(arguments){ return db.get(id) }) )),arguments,this)}, function() { document=arguments[0]; }),__oni_rt.Fcall(0,__oni_rt.Return,__oni_rt.Nblock( function(arguments){ return document; }) )),arguments, this)}; }))), this.arguments, this);
  • 97.
    Ryan Dahl -node.js “I will be removing wait() in the next release of Node. It has already been removed from the documentation.” “A proper implementation of wait() necessitates true coroutines” “This sort of mental complication is exactly what I'm trying to avoid in Node.” http://groups.google.com/group/nodejs/msg/df199d233ff17efa
  • 98.
    Take it easy No wait() Just flow control
  • 99.
    Sequence 1 //  async  sequential  computation sequence(get,  filter,  process) function  get(resume)  { $.get(url,  function(data)  { resume(data) }) } function  filter(resume,  data)  {  ...  } function  process(resume,  data)  {  ...  }
  • 100.
    Sequence 2 //  async  sequential  computation function  sequence()  { var  steps  =  arguments.slice() var  doStep  =  function(val)  { var  next  =  steps.shift() if  (next)  { next.apply(null,  [doStep,  val]) } } doStep() }
  • 101.
    Functional programming first(fetchA,  fetchB,  fetchC) every(checkA,  checkB,  checkC) map(array,  mapper) filter(array,  filter)
  • 102.
    From imperative var  clicks =  0,  timeout  =  null $(“button”).click(function()  { clicks++ if  (clicks  ==  1)  { timeout  =  setTimeout(function()  { clicks  ==  0 }) } if  (clicks  ==  3)  { clearTimeout(timeout) clicks  =  0 $(this).trigger(“tripleclick”) } })
  • 103.
    To declarative $(button) .on(“click”) .times(3) .within(“1  second”) .trigger(“tripleclick”)
  • 104.
  • 105.