PDA

View Full Version : Serial execution of functions



XManBG
08-06-2011, 07:35 AM
Hi everybody,

is there an explicit way to guarantee that JS will execute certain functions in sequence and not parallel??

I have one function, which result is used in the next function, which action must be finished, to perform the next-third function. Unfortunately JS is not "waiting" for the first function to end, and executes the second without the result of the first, and the third without waiting for the second. Further the call of the third function brings nothing, because the second was failed.

It's confusing... and not like the "normal" programming languages, where each command is executed after the previous one.

Cheers

vwphillips
08-06-2011, 10:45 AM
please post the problem page

jscheuer1
08-06-2011, 01:01 PM
Yes to be specific we would need a link to the page. In general though the last function invokes the second using its return value to do something with, the second likewise with the first, ex:


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
function one(){
return document.getElementById('something').innerHTML;
}

function two(){
return one().replace(/span/g, 'div');
}

function three(){
document.getElementById('something').innerHTML = two();
}
</script>
</head>
<body>
<div id="something"><span>Some Text</span><span> Some More Text</span></div>
<input type="button" value="Go" onclick="three();">
</body>
</html>

But if one of the functions takes a while to do what it does, there might be problems. There might not be, but if there are, at that point you need a callback - say when function one is finished it runs function two. And when function two is done it runs function three, the order is reversed and we start at function one. If that's what's going on we would need to see the page.

If you want more help:

Please post a link to a page on your site that contains the problematic code so we can check it out.

XManBG
08-06-2011, 03:14 PM
Here is the problem: http://www.x-mediapro.de/jass.performance/index.html

At bottom left corner are 3 counters. Calling three times the same JS function


function imgcounter(whereareimg,whatext,wheretocount){
var n = 1;
var filenames = document.getElementById('note1').innerHTML;
function checkfiles(){
var img = new Image();
filenames += whereareimg + n + whatext;
img.src = whereareimg + String(n) + whatext;
img.onerror = function(){filenames += " Error<br /><br />";document.getElementById('note1').innerHTML = filenames;document.getElementById(wheretocount).innerHTML = (--n);};
img.onload = function(){filenames += " OK<br />";(++n);checkfiles();};
};
checkfiles();
};


I'm filling them out with the counted number of the pictures from 3 folders, as already helpfully discussed here (http://www.dynamicdrive.com/forums/showthread.php?t=50450). There are some test pictures in the folders according to menu point "fabrications/MX5/external" only.

This shall be the first action on page load, so that the numbers are already there, when someone is clicking through the menu. Unfortunately, this is not functioning correct: on IE only counter3 and sometimes counter2 are read, but noch counter1; on Chrome the counters are read on page load, but the working DIV class="working5" remains empty, and comes just after one refresh (F5), etc.

The page functionality requires, to allow bookmarking of the clicked menu position. So I've added this using the variable hash. If someone bookmarks that page: http://www.x-mediapro.de/jass.performance/index.html#exterior, the three counters have to be loaded before(!) the page is completed, and specially the DIV class="working5" is loaded. That's where the three counters are used to show the images in slider1 and slider2 (counter3 is for later slider3, which is not yet implemented).

Here I need this serial execution of functions:
1) Call the imgcount function really three consecutive times
2) Call the functions for preparing and loading DIV5
3) On menu click, the counters have to be checked again, and this before the next page is loaded, etc.

Did I completely explained the problem?!

ggalan
08-07-2011, 02:39 PM
doesnt jQuery's queue address this problem?
http://api.jquery.com/queue/

jscheuer1
08-07-2011, 03:42 PM
The jQuery queue() function is for animations.

I was looking at this one earlier and I realized it would take some time to really look at the code and to reread perhaps several times the confusing (at least to me) requirements to try to solve it.

One thing that struck me right off though was why use innerHTML? You could use getElementsByTagName() to get all of the child img tags of a particular element. But the real problem is likely to be that once you start creating new Image() objects and doing things off of their load events, you cannot know when those will fire. You may have to compromise on when the information is available.

I also thought that if you're already loading the images to find them and write their tags in the first place, you already know or could know everything you might want to about them without having to load them again.

Added Later:

I looked at the page. I can't find the code in your post anywhere.

XManBG
08-07-2011, 07:30 PM
Hi guys,

the code of the listed function is in the main.js file. Somewhere in the middle.

I think, that looking through the complete code, to find out why it is not working, is one complicated task... at least for a person, which didn't write it.

That's why I'm trying to generalize the question and the problem by asking, if it is possible to slow down a function call and more, to explicit serialize them. Yes ggalan, actually like jQuery "queue", or more like the "callback" function, which is integrated there almost in every function.

Partially, I could try to use setTimeout() to leave enough time for the first function to complete its task, and then launch the second one. This is perfectly working, but it is a bad idea, because its very unpredictable. Maybe I will rethink the function's structure later ...

At least, let's try to simplify the requirements:

1) Somehow the script have to look and estimate, how many pictures are in some known folders.
2) Depending on the number of pictures, "li"-s shall be created and some evaluations shall be made to prepare them to be click-able and scroll-able.
3) The new "li"-s shall be filled out with the found pictures.

Why do I have a problem?? Because at the moment, e.g. in Chrome and IE on the first click, the numbers of pictures are estimated, but the "li"-s are not created. They come not till second click on the same menu point.

jscheuer1
08-07-2011, 11:03 PM
You have the same problem here as in the other thread. Set the src property after the onload and onerror properties. That way the browser will know what it's supposed to do when the image loads or errors.

Once you have the proper order:


function imgcounter(whereareimg,whatext,wheretocount){
var n = 1;
var filenames = document.getElementById('note1').innerHTML;
function checkfiles(){
var img = new Image();
filenames += whereareimg + n + whatext;
img.onerror = function(){filenames += " Error<br /><br />";document.getElementById('note1').innerHTML = filenames;document.getElementById(wheretocount).innerHTML = (--n);};
img.onload = function(){filenames += " OK<br />";(++n);checkfiles();};
img.src = whereareimg + String(n) + whatext;
};
checkfiles();
};

you have a much better chance of success.

BTW - The function checkfiles has two natural callbacks in it. The first is the onload function. It fires every time an image loads successfully. It's an interim callback. The second is the onerror function. That fires the first time there are no more files in sequence that fit the criteria and is the final callback. If you want to chain to another function after checkfiles is done with it's current work, the onerror function would be the place to do it.

XManBG
08-10-2011, 07:48 PM
Hi John,

I've already changed the place of src row, as you've advised earlier. The "searching" is functioning now.

The whole idea is also functioning, only after setting the functions next to the imgcounter() to wait for 500ms, i.e. with setTimeout().

Anyway... I've succeed to make a move forward thanks to you :)

Cheers