0

I'm trying to pause a function until another function has completed its task. Is there anything similar to .ajaxComplete() but for the completion of a function?

This code should simply print out "test" quickly at first and then slow down (decelerate, if you will). As the number in the loop becomes higher, setTimeout becomes longer, hence, it prints "slower" as the loop goes on. Basically, I need the loop to pause until the function has printed.

edit - I updated my code. "test" is only printed once and nothing else happens.

 <html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
</head>
<body>

<input type="button" value="Display alert box" onclick="docWrite()" />
<script>

var b = 0;

function docWrite() {
   document.write("test");
   timeMsg();
}

function timeMsg() {
  b += 250;
  if (b < 5000) { //check the limit
     setTimeout("docWrite()", b - 250); //substract 250 (because we already added 250 before the first print
  }
}
</script>
</body>
</html>
5
  • You should avoid using global variables. It makes your code more difficult to understand. Commented May 7, 2012 at 12:14
  • 1
    //something to pause loop until docWrite is completed is not possible in the way you want it to be. With very few exceptions you cannot have blocking calls in JS. You need to work with callback functions to set what needs to run after an asynchronous operation has completed. Commented May 7, 2012 at 12:17
  • 1
    //something to pause loop until docWrite is completed --- this would freeze the browser and is inacceptable Commented May 7, 2012 at 12:21
  • @zerkms ~ not really; I can think of a few reasons why you'd want to block. Generally, it is though, I hear you. Commented May 7, 2012 at 12:23
  • Oh, and you'd probably want to check your for loop syntax. That's one heck of an infinite loop. Commented May 7, 2012 at 12:24

3 Answers 3

3

I think it would be better to let the timeout function start a new timeout function This would solve your problem and get rid of the for loop altogether. Simply call timeMsg() to start the example.

<script>

var b = 0;

function docWrite() {
    $('body').append("test");
    timeMsg();
}

function timeMsg() {
    b += 250;
    if (b < 5000) { //check the limit
        setTimeout(docWrite, b - 250); //substract 250 (because we already added 250 before the first print
    }
}

</script>

Modifying your own script I end up with this:

<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
</head>
<body>

<input type="button" value="Display alert box" onclick="timeMsg()" />
<script>

var b = 0;

function docWrite() {
   $("body").append("test");
   timeMsg();
}

function timeMsg() {
  b += 250;
  if (b < 5000) { //check the limit
     setTimeout(docWrite, b - 250); //substract 250 (because we already added 250 before the first print
  }
}
</script>
</body>
</html>
Sign up to request clarification or add additional context in comments.

5 Comments

Looking at this it makes sense, but I can't get it to work. I'll update my code above with the entire html page
the setTimeout("docWrite()", b - 250) should be replaced with setTimeout(docWrite, b - 250). Also you forgot the "var b = 0;" :). Got your script working with those fixes in chrome.
I tried it in firefox and IE, neither worked. Just displays "test" once. In the setTimeout, if I change docWrite to docWrite() all 20 "tests" are displayed at once.
Instead of document.write("test") use $('body').append("test"); document.write will replace the entire document.
Yes, the timeMsg() function ends after it has set the timeout. The docwrite() function is then called by the system when the timeout occurs. (In other words: it's not recursive).
0

You're going to have to add the callback to docWrite(). Have it run something (or the thing you want done after) by passing in a function to it.

function docWrite(callback) {
    document.write('test');
    // something like
    callback();
}

then you can structure it like this:

var b = 0;
function timeMsg(){
    var t = setTimeout(function () {
        docWrite(function () {
            // what to do after this finishes
            if (b > 5000) { return; }
            b += 250;
            timeMsg();
        })
    }, b);
}   

Comments

0

The following function could be used to fullfill your task:

function repeat(action, initial, slowdown, count, callback) {
    function next(time) {
       window.setTimeout(function() {
          if (count--) {
             action();
             next(time+slowdown);
          }
          else
             callback();
       }, time);
    }

    next(initial);
}

You can use it as follows:

repeat(docWrite, 0, 250, 5000/250, function() {
    $("body").append("done"); 
});

function docWrite(){
    $("body").append("test");
}​

Please note that if the action call back (docWrite) performs asynchronous calls, like animations itself for which you want to wait to complete before starting the next timer, then it becomes a little bit more complicated. Let me know if that is the case.

http://jsfiddle.net/JKEpK/4/

3 Comments

I'm not sure if this is working for you, but it's neither working in jsfiddle nor on localhost when I run it.
@user1104854 Which browser are you using and what errors do you get?
Okay ff fails because it doesn't like document.write() on delayed calls! Use this instead: jsfiddle.net/JKEpK/5

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.