views:

1016

answers:

5

Ive searched a lot of places for the answer to this seemingly simple problem, but Ive only found rather complicated answers involving classes, event handlers and callbacks (which seem to me to be a somewhat sledgehammer approach). I think callbacks may be useful but I cant seem to apply these in the simplest context. See this example:

<html>

<head>

<script type="text/javascript">
function myfunction()
{
    longfunctionfirst();
    shortfunctionsecond();
}
function longfunctionfirst()
{
    setTimeout('alert("first function finished");',3000);
}
function shortfunctionsecond()
{
    setTimeout('alert("second function finished");',200);
}
</script>

</head>

<body>

<a href="#" onclick="javascript:myfunction();return false;">Call my function</a>

</body>
</html>

In this, the second function completes before the first function; what is the simplest way (or is there one?) to force the second function to delay execution until the first function is complete?

Many thanks in advance. Tom

---Edit---

Thanks for all the replies so quickly!

So that was a rubbish example but thanks to David Hedlund I see with this new example that it is indeed synchronous (along with crashing my browser in the test process!):

<html>

<head>

<script type="text/javascript">
function myfunction()
{
    longfunctionfirst();
    shortfunctionsecond();
}
function longfunctionfirst()
{
    var j = 10000;
    for (var i=0; i<j; i++)
    {
        document.body.innerHTML += i;
    }
    alert("first function finished");
}
function shortfunctionsecond()
{
    var j = 10;
    for (var i=0; i<j; i++)
    {
        document.body.innerHTML += i;
    }
    alert("second function finished");
}
</script>

</head>

<body>

<a href="#" onclick="javascript:myfunction();return false;">Call my function</a>

</body>
</html>

As my ACTUAL issue was with jquery and IE I will have to post a separate question about that if I cant get anywhere myself!

A: 

In javascript, there is no way, to make the code wait. I've had this problem and the way I did it was do a synchronous SJAX call to the server, and the server actually executes sleep or does some activity before returning and the whole time, the js waits.

Eg of Sync AJAX: http://www.hunlock.com/blogs/Snippets%3A%5FSynchronous%5FAJAX

rampr
SJAX is typically a sign of bad design and I would encourage novices to avoid it until they understand its implications.
Justin Johnson
A: 

As per the title "How to force Sequential Javascript Execution?" couldn't you simply call the second function inside the first function?

<script type="text/javascript">
function myfunction()
{
    longfunctionfirst();
}
function longfunctionfirst()
{
    alert('done');
    shortfunctionsecond();
}

function shortfunctionsecond() {}
</script>

That's sequential/procedural and functionsecond only fires after functionfirst is done.

Javascript has no real concept of threading, for this reason Google Gears has the WorkerPool. You can fake it badly with setTimeout - it depends what you're doing with the 2 functions.

Chris S
now you're calling it twice, tho.
David Hedlund
This is not sequential. `shortfunctionsecond` will be executed before `longfunctionfirst`
Justin Johnson
I forgot to remove `shortfunction` from `myfunction`
Chris S
+8  A: 

Well, setTimeout, per its definition, will not hold up the thread. This is desirable, because if it did, it'd freeze the entire UI for the time it was waiting. if you really need to use setTimeout, then you should be using callback functions:

function myfunction() {
    longfunctionfirst(shortfunctionsecond);
}

function longfunctionfirst(callback) {
    setTimeout(function() {
        alert('first function finished');
        if(typeof callback == 'function')
            callback();
    }, 3000);
};

function shortfunctionsecond() {
    setTimeout('alert("second function finished");', 200);
};

If you are not using setTimeout, but are just having functions that execute for very long, and were using setTimeout to simulate that, then your functions would actually be synchronous, and you would not have this problem at all. It should be noted, though, that AJAX requests are asynchronous, and will, just as setTimeout, not hold up the UI thread until it has finished. With AJAX, as with setTimeout, you'll have to work with callbacks.

David Hedlund
You make me spare a lot of typing for writing the very same things: +1
Eineki
I'm glad someone got it ;)
Justin Johnson
Also, I should note that AJAX requests are *generally* asynchronous, but can be made to be synchronous.
Justin Johnson
@Justin: yes, that's a valid point, thanks for the remark. if the real case scenario of issue is indeed ajax-related, synchronous callbacks could be the solution
David Hedlund
(altho the async-with-callback approach probably still gives greater control and readability of the execution flow)
David Hedlund
He didn't ask for AJAX in the question
Chris S
@Chris: you're right about that, i only briefly touched on AJAX in my response, in the event that it was actually an AJAX issue he was dealing with in his real world example, but was just using setTimeout for a stripped down way to reproduce the issue. There are absolutely no grounds for *assuming* that that is the case, but you'll notice in my answer, I don't make that assumption, and I don't focus on AJAX.
David Hedlund
Thanks David. I was looking in the wrong place and used a bad example - thanks for clearing that up and expanding my javascript knowledge.
Tom
Don't get mr wrong your solution is very elogant and spot on, it's just sometimes Ajax seems to confused with boring old JavaScript
Chris S
A: 

In your example, the first function does actually complete before the second function is started. setTimeout does not hold execution of the function until the timeout is reached, it will simply start a timer in the background and execute your alert statement after the specified time.

There is no native way of doing a "sleep" in JavaScript. You could write a loop that checks for the time, but that will put a lot of strain on the client. You could also do the Synchronous AJAX call, as emacsian described, but that will put extra load on your server. Your best bet is really to avoid this, which should be simple enough for most cases once you understand how setTimeout works.

Franz
A: 

Hi All, I am an old hand at programming and came back recently to my old passion and am struggling to fit in this Object oriented, event driven bright new world and while i see the advantages of the non sequential behavior of Javascript there are time where it really get in the way of simplicity and reusability. A simple example I have worked on was to take a photo (Mobile phone programmed in javascript, HTML, phonegap, ...), resize it and upload it on a web site. The ideal sequence is :

  1. Take a photo
  2. Load the photo in an img element
  3. Resize the picture (Using Pixastic)
  4. Upload it to a web site
  5. Inform the user on success failure

All this would be a very simple sequential program if we would have each step returning control to the next one when it is finished, but in reality :

  1. Take a photo is async, so the program attempt to load it in the img element before it exist
  2. Load the photo is async so the resize picture start before the img is fully loaded
  3. Resize is async so Upload to the web site start before the Picture is completely resized
  4. Upload to the web site is asyn so the program continue before the photo is completely uploaded.

And btw 4 of the 5 steps involve callback functions.

My solution thus is to nest each step in the previous one and use .onload and other similar stratagems, It look something like this :

takeAPhoto(takeaphotocallback(photo) {
  photo.onload = function () {
    resizePhoto(photo, resizePhotoCallback(photo) {
      uploadPhoto(photo, uploadPhotoCallback(status) {
        informUserOnOutcome();
      });
    }); 
  };
  loadPhoto(photo);
});

(I hope I did not make too many mistakes bringing the code to it's essential the real thing is just too distracting)

This is I believe a perfect example where async is no good and sync is good, because contrary to Ui event handling we must have each step finish before the next is executed, but the code is a Russian doll construction, it is confusing and unreadable, the code reusability is difficult to achieve because of all the nesting it is simply difficult to bring to the inner function all the parameters needed without passing them to each container in turn or using evil global variables, and I would have loved that the result of all this code would give me a return code, but the first container will be finished well before the return code will be available.

Now to go back to Tom initial question, what would be the smart, easy to read, easy to reuse solution to what would have been a very simple program 15 years ago using let say C and a dumb electronic board ?

The requirement is in fact so simple that I have the impression that I must be missing a fundamental understanding of Javsascript and modern programming, Surely technology is meant to fuel productivity right ?.

Thanks for your patience

Raymond the Dinosaur ;-)