4

So, I have a delayed function called delayed1 that gets repeated everytime cond1 is true, the problem is, somewhere inside that delayed1 function do_something1() gets called and if cond3 is true, another delayed function called delayed2 gets called. Now the problem is I want delayed1 to wait until delayed2 is finished (that means until cond2 is false) and then resume again, which doesn't seem to be happening. Once delayed2 gets started, delayed1 doesn't wait for it to finish and then resume. Is there a way to do this? Hopefully I was clear enough...

function delayed2() {
    setTimeout(function () {
       do_something2();
        if ( cond2 ) {
            delayed2();
        }
    }, 1000)
}

function do_something1(){
    if ( cond3 ){
        delayed2();
    }
    else {
        something_else();
    }
}

function delayed1() {
    does_something_here();
    setTimeout(function () {
        do_something1();
        if ( cond1 ){
            delayed1();
        }
    }, 1000)

}
Pred
  • 69
  • 6

3 Answers3

3

I see what your are trying to do here. You may probably want to approach in a different way. The best way would be to use promises or Deferreds.

Here is the example using jquery deferreds of your given code.

var wait_a_second = $.Deffered();

$.when(wait_a_second)
    .then(does_something_here)
    .then(function(){
        if( cond1 ) delayed1();
    })

    .then(delayed1);


function delayed1(){
    var d = $.Deffered()

    // Your conditions and logic
    if( cond ) {
        d.resolve();
    }

    return d.promise();
}

function delayed2(){
    var d = $.Deffered();

    // Your conditions and logic
    if( cond ) {
        d.resolve();
    }

    return d.promise();
}

In short learn promises to manage async operations queue.

Vinay Aggarwal
  • 1,565
  • 1
  • 10
  • 19
2

You should use promises to implement synchronous execution in JS.

Promise is a mechanism which returns an object to which you can hook callbacks. These callbacks can be called once a specific function is done with execution. Here is how it applies to your situation.

You generally have 3 functions which depend on each other. The first one should wait for the second and the second one should wait for the third. In the first level the second function should return a Promise.

function delayed1() {

    does_something_here();

    setTimeout(function () {
        var promise = do_something1();

        promise.then(function(){
            if ( cond1 ){
               delayed1();
           }
        });

    }, 1000) 
}

Here is your second function. It creates a promise and returns it. Also inside its if ( cond3 ) it should wait for a promise from the third function. I'm not going to write your third function as I'm certain that you can do it yourself following this pattern.

function do_something1(){

   return new Promise(function(resolve){
       if ( cond3 ){
           var promise = delayed(2);

           promise.then(function(){ 
              resolve()
            }) 

       }
       else {
          something_else();
          resolve();
       }    
   })  


}
Charlie
  • 22,886
  • 11
  • 59
  • 90
  • So if I understood this correctly, I have to return another promise from the third function ( in this case called delayed2() ) and that should do the trick, right? – Pred Dec 16 '15 at 16:53
  • Shouldn't this do something then? https://jsfiddle.net/7esybcu9/ I know I did something wrong somewhere, I searched for promises online but just couldn't figure out a way to make them work in my particular case. Sorry – Pred Dec 16 '15 at 19:04
  • You have two problems there. One is that you don't run any function. Add `()` after the `delayed1` function. The other problem is that the `delayed2` function doesn't resolve anything. So, `promise.then` will never execute inside `do_something1`. Go through a promise tutorial (MDN) from the beginning. Do simple samples. Then build your case for two levels. Go for the 3rd level when you have good understanding about 2 level architecture. – Charlie Dec 17 '15 at 16:55
1

You can try using callbacks. Following is a basic representation:

var count = 0;

function delay1(callback) {
  setTimeout(function() {
    console.log("Delay 1");
    count++;
    if (count < 12) {
      if (count % 2 == 0) {
        delay1();
      } else {
        delay2()
      }
    }
    if (callback) {
      callback();
    }
  }, 1000);
}

function delay2(callback) {
  setTimeout(function() {
    console.log("Delay 2");

    if (count > 10) {
      delay1(function() {
        console.log("This is callback;")
      })
    } else if (count % 2 == 0) {
      delay2();
    } else {
      delay1()
    }

    if (callback) {
      callback();
    }
    count++;
  }, 1000);
}


delay1();
Rajesh
  • 24,354
  • 5
  • 48
  • 79
  • I used this as last resort, after trying the promises and Deferreds (unsuccessfully) and it worked exactly as I wanted it to, thanks a lot man :) Now if you're not a noob like me, I suggest using the 2 other solutions because they are more recommended and I'll have to learn using them myself, but I needed just a quick fix for this problem for now. Thanks again for your answer – Pred Dec 17 '15 at 16:38
  • I'm glad, I was able to help. Also I may be wrong but `promises` were invented because of a situation called as `callback hell`. You can refer [callbackhell](http://callbackhell.com/), [SO - Post](http://stackoverflow.com/questions/25098066/what-is-callback-hell-and-how-and-why-rx-solves-it) – Rajesh Dec 17 '15 at 16:42
  • 1
    Of course. Promises provide easy,short and novel mechanism to do what you do here with callbacks. – Charlie Dec 17 '15 at 17:00