concurrency - Is JavaScript guaranteed to be single-threaded? -
javascript known single-threaded in modern browser implementations, specified in standard or tradition? totally safe assume javascript single-threaded?
that's question. i'd love “yes”. can't.
javascript considered have single thread of execution visible scripts(*), when inline script, event listener or timeout entered, remain in control until return end of block or function.
(*: ignoring question of whether browsers implement js engines using 1 os-thread, or whether other limited threads-of-execution introduced webworkers.)
however, in reality isn't quite true, in sneaky nasty ways.
the common case immediate events. browsers fire these right away when code cause them:
<textarea id="log" rows="20" cols="40"></textarea> <input id="inp"> <script type="text/javascript"> var l= document.getelementbyid('log'); var i= document.getelementbyid('inp'); i.onblur= function() { l.value+= 'blur\n'; }; settimeout(function() { l.value+= 'log in\n'; l.focus(); l.value+= 'log out\n'; }, 100); i.focus(); </script>
results in log in, blur, log out
on except ie. these events don't fire because called focus()
directly, happen because called alert()
, or opened pop-up window, or else moves focus.
this can result in other events. example add i.onchange
listener , type in input before focus()
call unfocuses it, , log order log in, change, blur, log out
, except in opera it's log in, blur, log out, change
, ie it's (even less explicably) log in, change, log out, blur
.
similarly calling click()
on element provides calls onclick
handler in browsers (at least consistent!).
(i'm using direct on...
event handler properties here, same happens addeventlistener
, attachevent
.)
there's bunch of circumstances in events can fire whilst code threaded in, despite having done nothing provoke it. example:
<textarea id="log" rows="20" cols="40"></textarea> <button id="act">alert</button> <script type="text/javascript"> var l= document.getelementbyid('log'); document.getelementbyid('act').onclick= function() { l.value+= 'alert in\n'; alert('alert!'); l.value+= 'alert out\n'; }; window.onresize= function() { l.value+= 'resize\n'; }; </script>
hit alert
, you'll modal dialogue box. no more script executes until dismiss dialogue, yes? nope. resize main window , alert in, resize, alert out
in textarea.
you might think it's impossible resize window whilst modal dialogue box up, not so: in linux, can resize window as like; on windows it's not easy, can changing screen resolution larger smaller 1 window doesn't fit, causing resized.
you might think, well, it's resize
(and few more scroll
) can fire when user doesn't have active interaction browser because script threaded. , single windows might right. goes pot you're doing cross-window scripting. browsers other safari, blocks windows/tabs/frames when 1 of them busy, can interact document code of document, running in separate thread of execution , causing related event handlers fire.
places events can cause generated can raised whilst script still threaded:
when modal popups (
alert
,confirm
,prompt
) open, in browsers opera;during
showmodaldialog
on browsers support it;the “a script on page may busy...” dialogue box, if choose let script continue run, allows events resize , blur fire , handled whilst script in middle of busy-loop, except in opera.
a while ago me, in ie sun java plugin, calling method on applet allow events fire , script re-entered. timing-sensitive bug, , it's possible sun have fixed since (i hope so).
probably more. it's been while since tested , browsers have gained complexity since.
in summary, javascript appears users, of time, have strict event-driven single thread of execution. in reality, has no such thing. not clear how of bug , how deliberate design, if you're writing complex applications, cross-window/frame-scripting ones, there every chance bite you — and in intermittent, hard-to-debug ways.
if worst comes worst, can solve concurrency problems indirecting event responses. when event comes in, drop in queue , deal queue in order later, in setinterval
function. if writing framework intend used complex applications, doing move. postmessage
soothe pain of cross-document scripting in future.
Comments
Post a Comment