SitePoint Sponsor

User Tag List

Results 1 to 12 of 12
  1. #1
    ********* Ornithologist AtomicPenguin's Avatar
    Join Date
    May 2002
    Location
    Vancouver, BC
    Posts
    459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    General question about multithreading / non-sequential execution of JS code

    Hi folks,

    I've been writing JS for years and have often encountered situations where I had to stick code in setTimeout()'s in order for it to function the way it "should". This has always left me a little puzzled but I never got round to asking about it. Well, this problem just cropped up again and this time I really have to figure out what's going on.

    Here's a really simple example for illustration purposes (which I think is valid). Imagine the first line takes half a second to complete, and when it's done it dumps some HTML into "myid". Inside the HTML is a textfield with an ID of "myinputfield".

    Code:
    document.getElementById("myid").innerHTML = mystr.replace(/some complicated regexp/g, str);
    document.getElementById("myinputfield").value = "something";
    When that runs, unless you stick the second line in a timeout, you (could) get an error since it doesn't think the ID exists.

    So what's going on here, exactly? Where's the lag happening?

    I've read that javascript doesn't support multithreading - but isn't this multithreading? It runs the second statement before completing the first. Why would it ever do this?

    Surely JS should execute statements sequentially, running one statement after the next - always. Is there some sort of JS engine optimization going on in the browser that lets it think that maybe those statements aren't related, so it doesn't wait for the first to complete before executing the second?

    I'd really like to identify the situations in which problems like this can occur, so I can plan for them. Up to this point I've just been working empirically; write some code, check in the browsers. Write some code, check in the browsers. Pretty daft.

    Any information you could provide would be very welcome!
    Last edited by AtomicPenguin; May 14, 2007 at 14:23.
    A.P.

    generatedata.com - free JS/PHP/MySQL random test data generator.
    Form Tools - free PHP/MySQL form processor.

  2. #2
    CSS & JS/DOM Adept bronze trophy
    Join Date
    Mar 2005
    Location
    USA
    Posts
    5,482
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In this case, it's because you're using the non-standard innerHTML property. The browser isn't fully evaluating it until the function exits.
    We miss you, Dan Schulz.
    Learn CSS. | X/HTML Validator | CSS validator
    Dynamic Site Solutions
    Code for Firefox, Chrome, Safari, & Opera, then add fixes for IE, not vice versa.

  3. #3
    ********* Ornithologist AtomicPenguin's Avatar
    Join Date
    May 2002
    Location
    Vancouver, BC
    Posts
    459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Kravvitz,

    Does this situation only arise with non-standards functionality, like innerHTML? That seems unlikely...

    When you say the browser isn't fully rendering it until the function exits, do you mean that encapsulating the laggy code in a separate function will ensure that the code gets completely executed before continuing in the branch that calls it? In my experience, I seem to remember this not always being the case...

    (I honestly have no clue about what's going on behind the scenes with JS execution, but I suspect that that will shed some light on the problem.)
    A.P.

    generatedata.com - free JS/PHP/MySQL random test data generator.
    Form Tools - free PHP/MySQL form processor.

  4. #4
    CSS & JS/DOM Adept bronze trophy
    Join Date
    Mar 2005
    Location
    USA
    Posts
    5,482
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm not sure. I rarely use code that isn't part of DOM2. (The major exception is IE's event model.)

    I suppose you could try something like the following, but I don't know if it would always make a difference.
    Code:
    fucntion setInnerHTML(el,str) {
      el.innerHTML = str;
    }
    We miss you, Dan Schulz.
    Learn CSS. | X/HTML Validator | CSS validator
    Dynamic Site Solutions
    Code for Firefox, Chrome, Safari, & Opera, then add fixes for IE, not vice versa.

  5. #5
    ********* Ornithologist AtomicPenguin's Avatar
    Join Date
    May 2002
    Location
    Vancouver, BC
    Posts
    459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Kravvitz!

    Yeah, I usually manage to fluff my way to a solution, but I was rather hoping on actually figuring out precisely why these problems occur; why javascript occasionally executes (or appears to execute) lines of code non-sequentially.

    Anybody?
    A.P.

    generatedata.com - free JS/PHP/MySQL random test data generator.
    Form Tools - free PHP/MySQL form processor.

  6. #6
    SitePoint Enthusiast
    Join Date
    Jan 2007
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have not had this exact situation before even though I do a lot of similar tricks with Javascript, I develop multiplayer AJAX games.

    About multithreading, you cannot have real multithreading in JS. You may be able to run pieces of code out of order with setTimeout and setInterval but no running piece of JS code will ever be interrupted so that another one will run unless it itself terminates, for example:

    setTimeout('foo()', 1000);
    takes_time_func();

    even if takes_time_func() takes 1 hour to run, foo() will not be called until it finishes and returns the execution back to the browser. This is why you don't need locks or other means to control critical areas in JS. Any method you write is guaranteed to run to completion before anything else can run.

    About innerHTML being non-standard, yes, but.... it's way fast. For example if I am building a list of players as they join and leave the game in a panel, using appendChild() etc took something like 150 millis for 200 users while with innerHTML just 1 millisecond. If you are doing something small and can afford to use the standards then fine, but I deal with a very fast changing env so I use innerHTML almost exclusively.

    I have never had the problem you describe even though it sounds like I should have had it because I think I have written similar code. But definitely the browser will render the layout after the JS code returns and not as it goes. So even though you assign innerHTML it (the browser) may not update its document structures etc until the function returns at which point it also renders the layout on screen. So the reason setTimeout() helps here is not by executing that code later in time but because it allows the function to return control back to the browser in the meantime.

    This is all from experience for me too, I am not a theoretical expert of any kind on JS, maybe the real Gurus can enlighten us

  7. #7
    ********* Ornithologist AtomicPenguin's Avatar
    Join Date
    May 2002
    Location
    Vancouver, BC
    Posts
    459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Johnny.

    Thought I'd just *bump* it to see it I can catch a few more responses...!
    A.P.

    generatedata.com - free JS/PHP/MySQL random test data generator.
    Form Tools - free PHP/MySQL form processor.

  8. #8
    ********* Ornithologist AtomicPenguin's Avatar
    Join Date
    May 2002
    Location
    Vancouver, BC
    Posts
    459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Howdy folks.

    Just thought I'd add some closure to this thread. I ended up finding a non-setTimeout solution to this, and explain the whole shebang here:
    http://www.benjaminkeen.com/?p=136

    To summarize: JS is sequentially executed (duh!). The reason you need the timeout is because although the HTML inserted by innerHTML has in fact been inserted into the page, it hasn't been converted to DOM elements, and as such, elements within it can't be "reached" by a document.getElementById() call immediately following the innerHTML statement. So even though technically the innerHTML statement has been executed, the browser hasn't completed its task of adding the nodes.

    Hope this helps other people who've been as puzzled as I have! :-)
    A.P.

    generatedata.com - free JS/PHP/MySQL random test data generator.
    Form Tools - free PHP/MySQL form processor.

  9. #9
    SitePoint Guru
    Join Date
    Mar 2004
    Location
    Earth
    Posts
    406
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nah you don't need all that queing business, there's a much simpler solution: http://domscripting.com/blog/display/99

  10. #10
    ********* Ornithologist AtomicPenguin's Avatar
    Join Date
    May 2002
    Location
    Vancouver, BC
    Posts
    459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Man, I wish you'd been around a week ago when I originally posted this! :-)

    Are you sure this solves my problem, though? I'm not sure it does. Very interesting article, but in fact I'm not totally clear on precisely what problem it's solving! He merely mentioned "screwiness" caused by using innerHTML on IE. My problem wasn't an IE issue, but in all browsers.

    Also, it seems as though adding the innerHTML into a separate DOM node wouldn't solve the timing problem - the browser still has to do the work of converting the innerHTMLed content into DOM nodes.

    Okay, guess I'll just have to test this out. It would be a much nicer solution, agreed.
    A.P.

    generatedata.com - free JS/PHP/MySQL random test data generator.
    Form Tools - free PHP/MySQL form processor.

  11. #11
    SitePoint Guru
    Join Date
    Mar 2004
    Location
    Earth
    Posts
    406
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh, well maybe I misunderstood. I've never had any problems manipulating newly created elements, but maybe that's because I never use innerHTML in this way I assumed that you were describing the same problem as Jeremy talks about there (that elements inserted using innerHTML don't [necssarily] exist in the DOM [immediately]). But perhaps not. Like I say, I've never encountered this problem.

    Have you got a test case for failure?

  12. #12
    ********* Ornithologist AtomicPenguin's Avatar
    Join Date
    May 2002
    Location
    Vancouver, BC
    Posts
    459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No, no test case - I was simply developing it directly and didn't save an older, broken, version of the code. In retrospect, quite a lack of foresight on my part - but at the time I was too stoked that it was actually WORKING to care.

    But once I get a little time I'm going to re-open this and try Jeremy's solution. It's that his code WILL fix my problem, which would be marvellous. No more fussy queues.

    Thanks again, brothercake!
    A.P.

    generatedata.com - free JS/PHP/MySQL random test data generator.
    Form Tools - free PHP/MySQL form processor.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •