Reputation: 127
i want to build a javascript class to register several different functions to execute a single common callback, all registered functions should execute asynchronously and then once all of them are finished, it should execute the defined callback function.
We should also be able to define a maximum time before the callback function executes. For example if we define that as 3000 and it takes more than 3000 ms for all registered functions to return, it should proceed to execute callback function even though the ajax functions have not finished retuning.
To be clear, this code needs to be flexible, standalone and reusable
To assume that any function that we register will implement a call to a function that we define at some point within it mark its completion. for eg. at the end of my function i'll enter myClass.markDone() to let the class know the function has completed executing
Is it possible using javascript or with angular.js and without jquery?
Upvotes: 0
Views: 175
Reputation: 4106
I asked for clarification in a comment already, but I went ahead and started drafting a solution. Here's what I came up with, hope this is what you meant:
var AsyncBatch = function() {
this.runnables = new Set();
};
AsyncBatch.prototype = {
runnables: null,
timeoutId: 0,
add: function(runnable) {
this.runnables.add(runnable);
},
start: function() {
this.timeoutId = window.setTimeout(this.timeout.bind(this), 3000);
let promises = [];
for (let runnable of this.runnables) {
promises.add(new Promise(resolve => {
runnable(resolve);
}));
}
Promise.all(promises).then(() => this.allDone());
},
allDone: function() {
if (this.timeoutId == 0) return;
window.clearTimeout(this.timeoutId);
this.finish();
},
timeout: function() {
this.timeoutId = 0;
this.finish();
},
finish: function() {
// Do something here when all registered callbacks are finished OR the batch timed out
},
};
Here's how you would use this:
AsyncBatch
..add()
as many times as you want, passing a function. This functions should expect a single parameter, which is the callback it should invoke when its job is done..start()
on the AsyncBatch
instance. It will execute all runnables asynchronously, as well as start a timer..allDone
will cancel the timer and execute .finish()
..finish()
, and sets the timerId
to 0 so that .finish()
won't be called again when the runnables all finish.Upvotes: 0
Reputation: 759
To achieve this take a look at these angular built in modules:
https://docs.angularjs.org/api/ng/service/$q
https://docs.angularjs.org/api/ng/service/$timeout
Here is an example implementation on plunkr:
qAllWithTimeout([
makePromise(function(callback) {
// Mock async call 1
setTimeout(callback, 200);
}),
makePromise(function(callback) {
// Mock async call 2
setTimeout(callback, 500);
}),
makePromise(function(callback) {
// Long running mock async call 2
setTimeout(callback, 10500);
})
], 3000)
.then(function() {
$scope.state = 'ready';
})
http://plnkr.co/edit/hNo9kJmKIR4hEoNk9pP2?p=preview
Upvotes: 1
Reputation: 3580
iam not sure this will work, am not tested. this may give you some idea.
function TestFun(callback, timeout){
this._callback = callback;
this._timeout = timeout;
this._forceFinish = false;
this.fun_list = [];
this.RegisterFun = function(fun){
this.fun_list.push(fun);
};
this.startCount = -1;
this.finishCount = 0;
this.timeOutFunction= function(){
this.startCount++;
fun_list[this.startCount]();
this.commonCallback();
}
this.Start = function(){
for(var i=0; i <this.fun_list.length ;i++){
setTimeout( this.timeOutFunction, 0);
}
setTimeout( this.watcherFun, 1 );
};
this.commonCallback = function(){
if( this._forceFinish){
this._callback();
}else{
this.finishCount++;
if(this.finishCount == this.fun_list.length ){
this._callback();
}
}
}
this.watcherFun = function(){
if( this._timeout !=0 ){
this._timeout-1;
setTimeout( this.watcherFun, 1 );
}else{
this._forceFinish = true;
this.commonCallback();
}
}
}
//usage
var funMngr = new TestFun(finalFun, 60 * 1000);
funMngr.RegisterFun ( fun1 );
funMngr.RegisterFun ( fun2 );
funMngr.RegisterFun ( fun3 );
funMngr.Start();
function finalFun(){
alert("all functions executed" );
}
Upvotes: 0