Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute function queue in javascript

I'm trying to create a function queue with several functions in it. After the creation i want to execute each function in it's turn. But these function have delayed instructions inside of them, so i want to wait for each of the functions to complete its execution before the continuing.

My attempts:

var funqueue = [];
funqueue.push( function() {fun1() });
funqueue.push( function() {fun2() });
funqueue.push( function() {fun3() });
executeFunctionQueue(funqueue);

Where the execute function is:

function executeFunctionQueue(funqueue){
    var fun1=funqueue.pop;
    $.when(fun1()).then(executeFunctionQueue(funqueue));
}

But this does not work. How should i do it?

like image 465
ido4848 Avatar asked Aug 15 '15 19:08

ido4848


2 Answers

Try utilizing .queue() , .promise() ; see also Change easing functions on animations in jQuery queue

function fun1() {
  return $.Deferred(function(dfd) {
    setTimeout(function() {
      dfd.resolve(1)
    }, 1500)
  }).promise().then(msg)
}

function fun2() {
  return $.Deferred(function(dfd) {
    setTimeout(function() {
      dfd.resolve(2)
    }, 1500)
  }).promise().then(msg)
}

function fun3() {
  return $.Deferred(function(dfd) {
    setTimeout(function() {
      dfd.resolve(3)
    }, 1500)
  }).promise().then(msg)
}

var funqueue = [];
funqueue.push(function() {
  return fun1()
});
funqueue.push(function() {
  return fun2()
});
funqueue.push(function() {
  return fun3()
});

function msg(data) {
   if (data === "complete") console.log(data)
   else $("body").append(data + "<br>")
}

function executeFunctionQueue(funqueue) {
  var deferred = funqueue.pop();
  return deferred().then(function() {
      // set `this` within `$.queue()` , `.then()` to empty object `{}`,
      // or other object
      return $({}).queue("fun", $.map(funqueue, function(fn) {
        return function(next) {
          // return `next` function in `"fun"` queue
          return fn().then(next)
        }
      })).dequeue("fun").promise("fun")
      .then(function() {
        // return "complete" string when `fun` queue empty
        return "complete"
      })
    });
}

executeFunctionQueue(funqueue)
.then(msg);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>

Alternatively , using $.when()

function executeFunctionQueue(funqueue) {
  return $.when(!!funqueue[funqueue.length - 1] 
                ? funqueue.pop().call().then(function() {
                  return executeFunctionQueue(funqueue)}) 
                : "complete")
}

executeFunctionQueue(funqueue)
.then(function(complete) { 
  console.log(complete) 
});

function fun1() {
  return $.Deferred(function(dfd) {
    setTimeout(function() {
      dfd.resolve(1)
    }, 1500)
  }).promise().then(msg)
}

function fun2() {
  return $.Deferred(function(dfd) {
    setTimeout(function() {
      dfd.resolve(2)
    }, 1500)
  }).promise().then(msg)
}

function fun3() {
  return $.Deferred(function(dfd) {
    setTimeout(function() {
      dfd.resolve(3)
    }, 1500)
  }).promise().then(msg)
}

var funqueue = [];
funqueue.push(function() {
  return fun1()
});
funqueue.push(function() {
  return fun2()
});
funqueue.push(function() {
  return fun3()
});

function msg(data) {
  if (data === "complete") console.log(data)
  else $("body").append(data + "<br>")
}

function executeFunctionQueue(funqueue) {
  return $.when(!!funqueue[funqueue.length - 1] 
                ? funqueue.pop().call().then(function() {
                  return executeFunctionQueue(funqueue)}) 
                : "complete")
}

executeFunctionQueue(funqueue)
.then(msg);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
like image 166
guest271314 Avatar answered Sep 21 '22 06:09

guest271314


If you have functions that return Promises, this can be done very simply with a function like sequence:

// sequence :: [(undefined -> Promise<undefined>)] -> Promise<undefined>
function sequence(fns) {
    var fn = fns.shift();
    return fn ? fn().then(sequence.bind(null, fns)) : Promise.resolve(undefined);
}

sequence assumes that your asynchronous/Promise-returning functions do not take any inputs and do not produce any outputs (that they are merely being called for side-effects.)

An example usage of the sequence function is:

sequence([f1, f2, f3]);

function f1() {
    return new Promise(function (res) {
        setTimeout(function () {
            console.log('f1');
            res();
        }, 100);
    });
}

function f2() {
    return new Promise(function (res) {
        setTimeout(function () {
            console.log('f2');
            res();
        }, 1100);
    });
}

function f3() {
    return new Promise(function (res) {
        setTimeout(function () {
            console.log('f3');
            res();
        }, 10);
    });
}

This will log out 'f1', 'f2', and 'f3' in order with the varying, specified time delays in between.

like image 42
Noah Freitas Avatar answered Sep 24 '22 06:09

Noah Freitas