www.webdeveloper.com
Results 1 to 12 of 12

Thread: setTimeout blocking recursive call

  1. #1
    Join Date
    Oct 2007
    Posts
    28

    setTimeout blocking recursive call

    I'm using this function to fade elements in and out:
    Code:
       
    this.fadeElement = function() {
            var O = this;
            var fading = this.fading;
    
            fading.currOpac += fading.sliceOpac;
    
            if (fading.rising)
                fading.currOpac = fading.currOpac > fading.endOpac ? fading.endOpac : fading.currOpac;
            else
                fading.currOpac = fading.currOpac < fading.endOpac ? fading.endOpac : fading.currOpac;
    
            O.setOpacity(fading.el, fading.currOpac);
    
            if (fading.currOpac == fading.endOpac) {
                clearTimeout(O.fading.timer);
    
                if (O.nextFunc.fp != null)
                    O.nextFunc.timer = setTimeout(function() { O.nextFunc.fp.apply(O, O.nextFunc.args) }, 100);
    
                return;
            }
    
            O.fading.timer = setTimeout(function() { O.fadeElement() }, fading.tmsDelay);
        }
    ...and it has been working just fine until a need arose to call the function two times consecutively, like this:
    Code:
    O.fading.setupFading(O.divPictureFrame, opacPicFrame, 0, 200, 20);
            O.nextFunc.fp = null;
            O.nextFunc.args = [];
            O.fadeElement();
    
            O.fading.setupFading(O.divOverlay, opacOverlay, 0, 300, 20);
            O.nextFunc.fp = null;
            O.nextFunc.args = [];
            O.fadeElement();
    ...now, when the first call reaches setTimout, it falls through to second call and disrupts the process, so I'm wondering if there is a way to to create a blocking version of recursive function using setTimeout?

  2. #2
    Join Date
    Sep 2008
    Posts
    48
    I'm sorry for offtopic but this is very hard.In this JavaScript forum all are beginners.Change title to Attn:setTimeout.......

  3. #3
    Join Date
    Sep 2008
    Posts
    45
    try this:

    make O.fading.timer an array instead ( Otimer=new Array )

    when u call O.fadeElement();
    do this:

    O.fadeElement(1);

    then in your script

    function(v)
    {
    clearTimeOut(Otimer[v])
    setTimeOut("whatever with the v id") // you have to carry that id through the time outs

    in this way u dont disrupt the different (id) timeouts.

  4. #4
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787

    resolved

    that look complicated, and without seeing the code to setupFading, it's hard to see whats going on.

    you might have better luck with this simpler code i wrote:

    Code:
    function fade(elm, In, cb ){ // element, boolFadeIn, callback 
         var i=1, ii = 1, st=setTimeout, es=elm.style, del=fade.del||40;
    	if(cb && cb.charAt){ cb = Function("element", "hidden", cb); }
    	if(In){
    		es.display= elm.od || "block";
    	   	for ( i = 1; i < 11; i++){   
    	      		st(  function(){ trans(elm, ii++ * 10);}, i * del );
    		} 
    	   	st(  function(){ es.filter=null; if(cb){ cb.call(elm,elm,100);}  }, 12 * del );
    	}else{
    		 elm.od =  es.display !== "none" ? es.display : "auto";
    		 for ( i = 1; i < 11; i++){   
    		 	st(  function(){ trans(elm, (10 - ii++) * 10);}, 400 - i * del );
    	 	}
    	   	st(  function(){ es.display="none"; if(cb){ cb.call(elm,elm,0);} }, 12 * del );
    	  }
    }//end fade
    
    function trans(elm, opacity) {  elm.style.opacity = (opacity / 100);}
    function transIE(elm, opacity) {   elm.style.filter = "alpha(opacity=" + opacity + ")";}
    if(window.ActiveXObject){ trans= transIE; }
    
    // args: fade(element, boolean_fadeIn);
    //usage: fade an element out: fade(elm); 
    //      fade an element in: fade(elm, true);
    i wrote to have minimal CPU impact, and it is self-contained, so you should be able to run multiple fades at once.

    EDIT:

    i replaced with a slightly more complex version, with callbacks.
    you can pass a function that unlocks the fading as a callback, or perhaps schedule them by passing a function to fade the next after the first is done.
    i see why i added the callback feature now...
    Last edited by rnd me; 09-30-2008 at 05:31 AM.

  5. #5
    Join Date
    Oct 2007
    Posts
    28
    Thanks for replying j0n0, but this still makes second call run while the first call is still in progress. What I would like to do is to create a "blocking" version of fadeElement that doesn't give control until the end condition is met.

    O.fadeElement();

    //somefunction doesn't get executed until O.fadeElement is completely done

    somefunction();

  6. #6
    Join Date
    Sep 2008
    Posts
    45
    ok let me try explain this way (and this is where rnd me is right)
    (ignore my previous code)

    you can call the same function
    without disrupting previous calls to that same function
    provided you timeouts are id-ed or unique

    call=new array()

    var call[0]=setTimeout("doNow(0,other_arguments_Here)",100) // where 0 is the id or the timeout

    function doNow(v)
    {
    clearTimeout(call[v])
    // do your opacity stuff here
    call[v]=("doNow(0,other_arguments_Here)",100)
    }

  7. #7
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    Quote Originally Posted by isvaljek View Post
    Thanks for replying j0n0, but this still makes second call run while the first call is still in progress. What I would like to do is to create a "blocking" version of fadeElement that doesn't give control until the end condition is met.

    O.fadeElement();

    //somefunction doesn't get executed until O.fadeElement is completely done

    somefunction();
    if you know the delay and the number of steps, multiply the two, add a 50ms buffer, and use the result to setTimeout your second call.


    Code:
    O.fading.setupFading(O.divPictureFrame, opacPicFrame, 0, 200, 20);
            O.nextFunc.fp = null;
            O.nextFunc.args = [];
            O.fadeElement();
    
    var steps = 255;
    var del = 20;
    var runtime = (steps * del) + 50;
    
    setTimeout(){function(){
            O.fading.setupFading(O.divOverlay, opacOverlay, 0, 300, 20);
            O.nextFunc.fp = null;
            O.nextFunc.args = [];
            O.fadeElement();
    } , runtime );
    youll have to figure out where to plug in the real numbers, but you get the idea.
    im guessing it 100, but i dont know the arguments for the setup function.
    Last edited by rnd me; 09-30-2008 at 05:43 AM.

  8. #8
    Join Date
    Sep 2008
    Posts
    45
    var call[0]=setTimeout("doNow(0,other_arguments_Here)",100)
    var call[1]=setTimeout("doNow(1,other_arguments_Here)",100)
    var call[2]=setTimeout("doNow(2,other_arguments_Here)",100)
    var call[3]=setTimeout("doNow(3,other_arguments_Here)",100)
    var call[4]=setTimeout("doNow(4,other_arguments_Here)",100)

  9. #9
    Join Date
    Sep 2006
    Location
    Copenhagen, Denmark
    Posts
    1,253
    it falls through to second call and disrupts the process,
    No. JavaScript is single threaded. Once a function is executing you must wait for it to finish. No process (function) can interrupt another but maybe you mean something else?
    if there is a way to to create a blocking version of recursive function using setTimeout?
    What exactly do you mean by that? Can you give a simplified example?

    This
    Code:
    O.fadeElement();
    
    //somefunction doesn't get executed until O.fadeElement is completely done
    
    somefunction();
    can not be done using native constructs. You will have to

    1: call somefunction as the last statement in O.fadeElement
    2: schedule both functions to run at a specific timeout.
    3: make a function which checks for whether 0.fadeElement has returned or not (by having fadeElement set a variable just before returning) and have this function run with setInterval. This master function can then execute new functions depending on the return value from O.fadeElement.

    Option 3 could look something like
    Code:
    function master() {
      if (O.fadeElement.running)
        return;
      else
        somefunction();
    }
    
    // Setup master function to run every 10th millisecond
    setInterval(master,10);
    then alter fadeElement to
    Code:
    function fadeElement() {
      arguments.callee.running = true;
      //  ...
      //  do whatever
      //  ...
        arguments.callee.running = false;
    }

  10. #10
    Join Date
    Oct 2007
    Posts
    28
    Quote Originally Posted by rnd me View Post
    that look complicated, and without seeing the code to setupFading, it's hard to see whats going on.

    you might have better luck with this simpler code i wrote:

    Code:
    function fade(elm, In, cb ){ // element, boolFadeIn, callback 
         var i=1, ii = 1, st=setTimeout, es=elm.style, del=fade.del||40;
    	if(cb && cb.charAt){ cb = Function("element", "hidden", cb); }
    	if(In){
    		es.display= elm.od || "block";
    	   	for ( i = 1; i < 11; i++){   
    	      		st(  function(){ trans(elm, ii++ * 10);}, i * del );
    		} 
    	   	st(  function(){ es.filter=null; if(cb){ cb.call(elm,elm,100);}  }, 12 * del );
    	}else{
    		 elm.od =  es.display !== "none" ? es.display : "auto";
    		 for ( i = 1; i < 11; i++){   
    		 	st(  function(){ trans(elm, (10 - ii++) * 10);}, 400 - i * del );
    	 	}
    	   	st(  function(){ es.display="none"; if(cb){ cb.call(elm,elm,0);} }, 12 * del );
    	  }
    }//end fade
    
    function trans(elm, opacity) {  elm.style.opacity = (opacity / 100);}
    function transIE(elm, opacity) {   elm.style.filter = "alpha(opacity=" + opacity + ")";}
    if(window.ActiveXObject){ trans= transIE; }
    
    // args: fade(element, boolean_fadeIn);
    //usage: fade an element out: fade(elm); 
    //      fade an element in: fade(elm, true);
    i wrote to have minimal CPU impact, and it is self-contained, so you should be able to run multiple fades at once.

    EDIT:

    i replaced with a slightly more complex version, with callbacks.
    you can pass a function that unlocks the fading as a callback, or perhaps schedule them by passing a function to fade the next after the first is done.
    i see why i added the callback feature now...
    I've given up on recursive version and went back to something similar to your version, but now I have a new problem: the program flow may interrupt the fading function, so now I need a reliable way to manage the timers returned by setTimeout, to be able to clear them when the need arises.

  11. #11
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    Quote Originally Posted by isvaljek View Post
    I've given up on recursive version and went back to something similar to your version, but now I have a new problem: the program flow may interrupt the fading function, so now I need a reliable way to manage the timers returned by setTimeout, to be able to clear them when the need arises.
    my method dispatches all the timeouts at once, so it's not a simple matter to clear the timeout.

    furthermore, canceling them would leave an element partially transparent.

    since they are all dispatched separately, they should not interrupt any other flow. if something is already on the stack, the timeout will be moved to the bottom of the stack.

    i don't really understand the point of canceling them.
    can you explain a little further and post the code you are working on?

  12. #12
    Join Date
    Oct 2007
    Posts
    28

    Smile

    Quote Originally Posted by rnd me View Post
    my method dispatches all the timeouts at once, so it's not a simple matter to clear the timeout.

    furthermore, canceling them would leave an element partially transparent.

    since they are all dispatched separately, they should not interrupt any other flow. if something is already on the stack, the timeout will be moved to the bottom of the stack.

    i don't really understand the point of canceling them.
    can you explain a little further and post the code you are working on?
    I decided to put them all into an array and clear them in one swoop when they're not needed anymore. This happens when user selects new image in my slideshow "app" (something like lightbox, but smaller); at that time previous image may or may not have finished fading in and thus my problem.

    Thanks for all your help guys, I appreciate it.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

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



Recent Articles