Download - Event Driven Javascript
Event Driven Javascript
[email protected]/fgalassi
• Event driven programming
• Event driven javascript• History of javascript design
Software components
exchangeinformation
Producersgive
information
Consumerstake
information
Taxonomy ofinteraction models
Who is the producer ?
KnownWhere’s Kenny?
Over There!
UnknownWhere’s Kenny?
Where’s Kenny?
Over There!
Who is the producer ?known unknown
How does information flow ?
PullWhere’s Kenny?
Over There!
PushLet me know
where’s Kenny
Ok
... later ...Hey! Over There!
How does information flow ?
known unknownpull
push
4 Models ofinteraction
known unknown
pull
push
RequestResponse
1.
Request Response
// method invocationweapon = armory.buy(“shuriken”)kenny = cartman.findKenny()kenny.kill(weapon)
SIMPLE
Request Response
SIMPLESEQUENTIAL
Request Response
SIMPLESEQUENTIAL
IMPERATIVE
Request Response
HUMAN
Request Response
SEQUENTIALIMPERATIVE
Request Response
TIGHT COUPLING
SEQUENTIALIMPERATIVE
Request Response
TIGHT COUPLING
INEFFICIENT
known unknown
pull
push
RequestResponse
2.
AnonymousRequest
Response
AnonymousRequest Response
The system decouplesinformation and its owner
AnonymousRequest Response
load balancer
AnonymousRequest Response
FAILOVERload balancer
AnonymousRequest Response
load balancer FAILOVER
EXTENSIBLE
AnonymousRequest Response
SYSTEMCOMPLEXITY
known unknown
pull
push
RequestResponse
3.
AnonymousRequest
Response
Callback
Callback
// observer patterncartman.findKenny( function(kenny) { kenny.kill(weapon)})
Don’t call usWe’ll call you
From Sequential
INPUT
STATE
COMPUTATION
OUTPUT
To State MachineINPUT STATE A
OUTPUT
INPUT STATE B
INPUT STATE C
COMPUTATION
COMPUTATION
Callback
Relinquish control
Just in time is optimal
Callback
Consumer
Producers
Callback
efficiency
Callback
efficiencyEXPLICITCONTROL
FLOW
known unknown
pull
push
RequestResponse
4.
AnonymousRequest
Response
Callback Event Driven
Callback +Anonymous
Request Response=
EVENTS
Home AutomationExample
EVENTS
FAILOVER +EXTENSIBLE +efficiency =-------------------------------------
power
systemCOMPLEXITY +
explicitcontrol flow =-------------------------------------chaos
REQUEST RESPONSECALLBACK
ANON.REQUEST
RESPONSE
EVENTS
Expressive Power
Complexity
Javascriptis
event* driven
* technically callback driven
NotJavascript
Fault
NotYourFault
Just anHARDER
problem
• Event driven programming
• Event driven javascript• History of javascript design
In the old days...
Netscape HeadquartersMay 1995
This guy had two problems...
Brendan EichCreator of Javascript
1. The world isConcurrent
... and so isbrowser
Network RequestsUser Input
LiveScript first shipped in betas of Netscape Navigator 2.0 inSeptember 1995
2. Very very veryshort time
BePragmatic
He could use
Threads ...Real preemptive
concurrency
ThreadsareEvil
He could use
Coroutines ...Emulated
cooperativeconcurrency
needs acomplex
scheduler
He was afunctional
guy
Not concurrent
Take it easy
Just non-blocking
Callbacks// callbacks give// non linear executionwally.takeJob(function work() ...)wally.getCoffee(function drink() ...)
// ... later ...// first drink coffee// then work
Simple event loop// make it look concurrentbutton.onclick(function() {...
})
UI update
Click handler
UI update
Click handler
Click handlerUI
eventqueue
timeUser click
Non-blocking I/O// network async apixhr.onreadystatechange = function(){...
})
// DOM manipulations are synchronous// but in memory so very fastdiv.innerHTML = “Hello”
Javascript won
Butsold its soul
for simplicity
One thread=
Freeze
No Wait()
function breakfast() {var bacon = bacon()var juice = orangeJuice()eat(bacon, juice)
}
Simple sequential
function bacon() {// get baconreturn bacon
}
computation
function breakfast() {var bacon = bacon()var juice = orangeJuice()eat(bacon, juice)
}
function bacon() {getBacon(function(bacon) {
// got bacon})
}
Async gets inwrong
return what?
Break computationfunction breakfast() { var callback = function(bacon) {
var juice = getOrangeJuice()eat(bacon, juice)
}bacon(callback)
}
function bacon(callback) {// get bacon asynccallback(bacon)
}
rest of computation
computation
Break morefunction breakfast() { var callback = function(bacon) {
var callback = function(juice) {eat(bacon, juice)
}getOrangeJuice(callback)
}bacon(callback)
}
rest of computation 1
computation
rest of computation 2
ContinuationPassing
Style
// simple sequential computation
function A() { return B() }function B() { return C() }function C() { return value }
A()
it’s Viral 1
it’s Viral // 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()
2
// simple sequential sleep
sleep(3000)doSomething()
sleepit’s Hard
// not so simple sleep
setTimeout(function() {doSomething()
}, 3000)
sleepit’s Hard
// simple sequential loop
images.forEach(function(url)var image = fetchImage(url)image.show()
}
loopit’s Hard
// fetchImage is async
images.forEach(function(url)fetchImage(url, function(image) {
image.show()})
}
loopit’s Hard
// Show them in the right order
function processImage() {var url = images.shift()if (url) {
fetchImage(url, function(image) {image.show()processImage()
})}
}processImage()
loopit’s Hard
Javascriptsacrificed
conveniencefor simplicity
... and it was the right choice
• Event driven programming
• Event driven javascript• History of javascript design
How can we tame
complexity?
AddWait()
stupid!
Easy// simple sequential sleep with wait/resume
sleep(3000)doSomething()
function sleep(msec) {wait(
setTimeout(function() {resume()
}, msec))
}
sleep
Beautiful
Already done !
http://stratifiedjs.org/
// write sequential logic
function doOpsABC() {waitfor {
var x = doOpA()}and {
var y = doOpB()}return doOpC(x,y)
}
Transform tocontinuation
passingstyle
http://nodejs.org/
// synchronous read
fs.read(path).wait()
Implementcoroutines
Back tocomplexity
Jeremy Ashkenas - CoffeeScript
“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.”
“Case in point, Stratified JS: A virtuoso performance of JavaScript compilation, but look at what it compiles into.”
https://github.com/jashkenas/coffee-script/issuesearch?state=closed&q=asynchronous#issue/350/comment/330116
Jeremy Ashkenas - CoffeeScript
var getDocument = function(){ waitfor(document) { resume(db.get(id)); } return document; };
var getDocument;__oni_rt.exec(__oni_rt.Seq(0,__oni_rt.Seq(0,__oni_rt.Nblock(function(arguments){ getDocument=function (){ 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.Nblock( 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);
“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.”
Ryan Dahl - node.js
http://groups.google.com/group/nodejs/msg/df199d233ff17efa
No wait()
Take it easy
Just control flow
Sequence// async sequential computationsequence(get, filter, process)
function get(resume) {$.get(url, function(data) {
resume(data)})
}
function filter(resume, data) { ... }function process(resume, data) { ... }
1
Sequence// 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()
}
2
Functional programming
first(fetchA, fetchB, fetchC, callback)every(checkA, checkB, checkC, callback)map(array, mapper, callback)filter(array, filter, callback)
The road is
taking yourcontrol flow
From imperative// complex triple click event
var clicks = 0, timeout = null
$(“button”).click(function() {clicks++if (clicks == 1) {
timeout = setTimeout(function() {clicks = 0
}, 1000)}if (clicks == 3) {
clearTimeout(timeout)clicks = 0$(this).trigger(“tripleclick”)
}})
To declarative$(button).on(“click”).times(3).within(“1 second”).trigger(“tripleclick”)
Questions?