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

Popular posts from this blog

javascript - Enclosure Memory Copies -

php - Replacing tags in braces, even nested tags, with regex -