SitePoint Sponsor

User Tag List

Results 1 to 8 of 8
  1. #1
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,608
    Mentioned
    24 Post(s)
    Tagged
    1 Thread(s)

    Lightbulb A working JavaScript sleep() function

    The following code allows you to put delays into your JavaScript provided that the process you are running is contained entirely within the one function and you don't try to put a delay into the middle of a loop.

    This example displays one line of text then waits five seconds then displays the second line then waits a further three seconds and then displays the third line - all in the same div over the top of one another.

    Code:
    <html>
    <head>
    </head>
    <body>
    <div id="text"></div>
    <script type="text/javascript">
    Function.prototype.allowSleep = function(n) {
      var i, f;
      if (!/^[$\w]+$/.test(n)) return;
      i = 0;
      f = this.toString().replace(/sleep\((.*?)\);/g , function(f,t) {i++; return n+".f"+i+" = function() {"+n+".func"+i+"();};\nsleep("+t+","+n+".f"+i+");\n"+(i==1?"":"}\n")+n+".func" + i +" = function() {";});
      eval(n+'='+f+'\n}');
    }
    sleep = function(t,f) {
      if (f === undefined) return;
      setTimeout(f,t);
    }
     
    afunc = function() {
      document.getElementById('text').innerHTML = 'first message';
      sleep(5000);
      document.getElementById('text').innerHTML = 'message the second';
      sleep(3000);
      document.getElementById('text').innerHTML = 'last message';
    }
    afunc.allowSleep('afunc'); // comment out to disable sleep
    afunc();
    </script>
    </body>
    </html>
    Note that any code following the end of the function will not be delayed by the sleep. Inserting the sleep into the middle of a loop will stop the code running at all as the code after the sleep is moved to a separate function.

    Does anyone have any suggestions on how to extend this so it works for those cases as well?
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,527
    Mentioned
    84 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by felgall View Post
    Note that any code following the end of the function will not be delayed by the sleep. Inserting the sleep into the middle of a loop will stop the code running at all as the code after the sleep is moved to a separate function.

    Does anyone have any suggestions on how to extend this so it works for those cases as well?
    Not on how to extend it, but I've slightly refactored the function so that it's easier to understand what is going on in there.

    Code javascript:
    Function.prototype.allowSleep = function (funcName) {
        if (!/^[$\w]+$/.test(funcName)) {
            return;
        }
        var i = 0,
            sleepFuncRx = /sleep\((.*?)\);/g,
            sleepInjector = function (dummy, time) {
                i += 1;
                var sleepFunc = funcName + '.f' + i,
                    afterSleepFunc = funcName + '.func' + i,
                    before = sleepFunc + ' = function() {' + afterSleepFunc + '();' + '};\n',
                    during = 'sleep(' + time + ',' + sleepFunc + ');\n',
                    nestedBrace = (i === 1 ? '' : '}\n'),
                    after = nestedBrace + afterSleepFunc + ' = function() {';
                return before + during + after;
            },
            sleepingFunc = this.toString().replace(sleepFuncRx, sleepInjector);
        eval(funcName + '=' + sleepingFunc + '\n}');
    };
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  3. #3
    SitePoint Wizard webcosmo's Avatar
    Join Date
    Oct 2007
    Location
    Boston, MA
    Posts
    1,437
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Another approach could use a global variable. On first call of the setTimeout it can check the variable to see if its a first call or not.
    On first call it can set the global variable to mark something as not first e.g. >0 value and no processing to be done with this.
    On succeeding calls simply clear time out.

    Just a thought.

  4. #4
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,527
    Mentioned
    84 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by webcosmo View Post
    Another approach could use a global variable.
    No - global variables are bad. Most especially globals should not be used when a local variable will do instead.
    Global Variables in JavaScript
    Global variables (from JSLint)
    Awful Parts of JavaScript

    These other places are about how to improve your usage of JavaScript, in ways that make your life easier and better.
    Avoid cluttering the global namespace
    From slide #17 of the JavaScript Best Practices presentation
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  5. #5
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,608
    Mentioned
    24 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by paul_wilkins View Post
    Not on how to extend it, but I've slightly refactored the function so that it's easier to understand what is going on in there.
    Paul, thanks for your response. As you do not have any suggestions for a way to bypass the limitations I mentioned I am closer to being convinced that this is as close as JavaScript can get to a sleep function that can be coded the same way as in other languages.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  6. #6
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,527
    Mentioned
    84 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by felgall View Post
    Paul, thanks for your response. As you do not have any suggestions for a way to bypass the limitations I mentioned I am closer to being convinced that this is as close as JavaScript can get to a sleep function that can be coded the same way as in other languages.
    I agree. Because JavaScript doesn't control it's execution context, techniques from other languages just aren't viable in that sort of regard. JavaScript just cannot afford to use the blocking context that would be required in which to achieve such a sleep function. The best way for javascript still seems to be to package up what is intended to be executed later on, and to use some kind of mediator pattern in which to manage the timings and execution of things.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  7. #7
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,608
    Mentioned
    24 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by paul_wilkins View Post
    The best way for javascript still seems to be to package up what is intended to be executed later on, and to use some kind of mediator pattern in which to manage the timings and execution of things.

    That's basically what my sleep() function does for the situations where the original script allows for it to be rewritten to do that using JavaScript itself to do the rewriting.

    Here's a similar script that produces a custom alert - subject to the same restrictions and using sm() and hm() as the show and hide functions for displaying the modal dialog (calling those functions in the modal dialog script I wrote six years ago at http://javascript.about.com/library/blmodald1.htm to save me having to rewrite that part while getting the rest to work).

    Code:
    alert = function(t,f) {
    var d, d2, e, n;
    if (f === undefined) return;
    d = document.createElement('div');
    d.id = 'alertbox';
    d.className ='dialog';
    d2 = document.createElement('div');
    d2.style.textAlign = 'center';
    e = document.createElement('span');
    n = document.createTextNode(t);
    e.appendChild(n);
    d2.appendChild(e);
    d2.appendChild(document.createElement('br'));
    e = document.createElement('button');
    n = document.createTextNode('OK');
    e.appendChild(n);
    e.id = 'alertbutton';
    d2.appendChild(e);
    d.appendChild(d2);
    document.getElementsByTagName('body')[0].appendChild(d);
    sm('alertbox',200,50);
    document.getElementById('alertbutton').onclick = f;
    }
    clearAlert = function() {
    var a = document.getElementById('alertbox');
    hm('alertbox');
    a.parentNode.removeChild(a);
    }
    
    Function.prototype.allowAlert = function(n) {
       var i, f;
      i = 0;
      f = this.toString().replace(/alert\((.*?)\);/g , function(x,t) {i++; return n+".f"+i+" = function() {clearAlert();\n"+n+".fa"+i+"();};\nalert("+t+","+n+".f"+i+");\n"+(i==1?"":"}\n")+n+".fa" + i +" = function() {";});
      eval(n+'='+f+'\n}');
    }
    
     
    afunc = function() {
      document.getElementById('text').innerHTML = 'first message';
      alert('one');
      document.getElementById('text').innerHTML = 'message the second';
      alert('two');
      document.getElementById('text').innerHTML = 'last message';
       }
    afunc.allowAlert('afunc');
    afunc();
    I still haven't got around to refactoring the code just yet - I usually leave that until after I am happy that it works as intended, plus these are still just experiments to see how closely I can reproduce the JavaScript alert() functionality while providing the ability to style it however you want in the web page (the sleep version was one step along the way). My modal dialog script is overdue for a rewrite so when I do that I'll incorporate a refactored version of this experiment into it.

    At least then beginners trying to emulate sleep() or wanting their own custom dialogs will be able to see a way to do it that at least works provided that all the code is inside the one function and they don't need to make any calls inside of loops.



    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  8. #8
    SitePoint Member
    Join Date
    Jun 2012
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi fellgal, I tried to send you a pm, but its seems you dont accept them, or it just wouldnt send to you. I am looking for a programmer to develop a web application and wanted to see if your interested and go over the details with you. Please send me a pm of how we could discuss this.

    Thanks


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
  •