Created
June 16, 2013 16:21
-
-
Save hoehrmann/5792533 to your computer and use it in GitHub Desktop.
Abusing JavaScript generators and yield one can create task schedulers that essentially allow to write code that waits without blocking for asynchronous events. Originally http://lists.w3.org/Archives/Public/www-archive/2008Jul/0009.html and http://lists.w3.org/Archives/Public/www-archive/2013Apr/0043.html The difference between the two versions…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function OnYieldWaitForEvent(cor, target, name, phase) { | |
var self = arguments.callee; | |
target.addEventListener(name, function(evt) { | |
// We need to unregister the listener to save resources | |
// and to avoid getting called if the event occurs again | |
evt.currentTarget.removeEventListener(name, self, phase); | |
// Resume the waiting function | |
cor.next(); | |
}, phase); | |
}; | |
function ExecWithOnYield(func) { | |
var generator = new func; | |
generator.next(); | |
// There is no arguments.generator or `this generator` yet | |
// and arguments.callee refers to the Function object, so | |
// we have to pass a self-reference to the instance. | |
generator.send(generator); | |
}; | |
function test() { | |
var self = yield; | |
// Create a new <img> object | |
var img1 = new Image(315, 48); | |
OnYieldWaitForEvent(self, img1, 'load', false); | |
img1.src = 'http://www.w3.org/Icons/w3c_main'; | |
yield; // wait for img1 'load' | |
// ... load more images here ... | |
// Now draw them all on a <canvas> | |
// Signal we are done so the event handler does not have to | |
// catch an exception that would otherwise be generated. | |
yield 'done'; | |
}; | |
ExecWithOnYield(test); | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function OnYieldWaitForEvent(target, name, useCapture) { | |
return function(resume) { | |
var listener; | |
listener = function(){ | |
target.removeEventListener(name, listener, useCapture); | |
resume(); | |
}; | |
target.addEventListener(name, listener, useCapture); | |
} | |
} | |
function ExecWithOnYield(func) { | |
var generator = new func; | |
var ExecOneStep; | |
ExecOneStep = function(){ | |
try { | |
var wrapped = generator.next(); | |
// TODO: what if `wrapped` throws `StopIteration`? | |
wrapped(ExecOneStep); | |
} | |
catch (e) { | |
if (e instanceof StopIteration) { | |
console.log("StopIteration"); | |
} else { | |
console.log("other exception"); | |
} | |
} | |
} | |
ExecOneStep(generator); | |
}; | |
function test() { | |
var img1 = new Image(315, 48); | |
img1.src = 'http://www.w3.org/Icons/w3c_main'; | |
yield OnYieldWaitForEvent(img1, 'load', false); | |
console.log("img1 has loaded when we get here"); | |
}; | |
ExecWithOnYield(test); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
With all the addEventListener, and removeEventListener would this cause issues for a ton of events? Like if you were to do mouse move tracking in a loop?
Using it for clicks would probably be ok.