Skip to content

Commit

Permalink
Repeat function call
Browse files Browse the repository at this point in the history
  • Loading branch information
Pradhan V committed Oct 27, 2017
1 parent 049247d commit bd1cae0
Show file tree
Hide file tree
Showing 3 changed files with 263 additions and 93 deletions.
106 changes: 106 additions & 0 deletions chain.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
'use strict';
//
const Chain = function Chain (delay, functionArray, callback) {
if (!(this instanceof Chain)) {
return new Chain(delay, functionArray);
}
if (delay) {
this.setDelay(delay);
}
if (functionArray) {
this.setFunctions(functionArray);
}
if (callback) {
this.setCallback(callback);
}
};
//
Chain.prototype.setDelay = function (millis) {
this._delay = millis;
};
//
Chain.prototype.setFunctionArgs = function (args) {
this._functionArgs = args;
};
//
Chain.prototype.setFunctions = function (functionArray) {
this._functionArray = functionArray;
};
//
Chain.prototype.setCallback = function (callback) {
this._callback = callback;
};
//
Chain.prototype.startCalls = function (...args) {
if (args && args.length > 0) {
this.setFunctionArgs(args);
}
return this._callFunctions(...[this._delay, this._functionArray].concat(this._functionArgs));
};
//
// functionArguments will have the return value from the previous function call
// and the original function arguments which was set or passed to startCalls function.
Chain.prototype._callFunctions = function (delay, functions, ...args) {
// the last argument will be the return value
const [previousResult] = args.slice(-1);
if (!functions || functions.length === 0) {
// if there are no functions to invoke then callback
if (this._callback) {
this._callback(previousResult);
}
return;
}
let fnReturnValue = null;
try {
// invoke the function
fnReturnValue = functions[0].apply(functions[0], args);
} catch (err) {
if (this._callback) {
this._callback.apply(this._callback, err);
}
return;
}
// remove the invoked function from the array
const nextFunctions = functions.slice(1);
// check if return value is another chain
if (fnReturnValue && fnReturnValue instanceof Chain && fnReturnValue._functionArray &&
fnReturnValue._functionArray[0]) {
// push the new chain's functions to the beginning of the original chain
nextFunctions.unshift(...fnReturnValue._functionArray);
// replace function arguments
if (fnReturnValue._functionArgs && fnReturnValue._functionArgs !== null &&
fnReturnValue._functionArgs.length > 0) {
fnReturnValue = fnReturnValue._functionArgs;
} else {
// [retvalue] = args;
fnReturnValue = previousResult;
}
}
// prepare arguments for the next function call
let callargs = [delay, nextFunctions];
// add original arguments
if (this._functionArgs) {
callargs = callargs.concat(this._functionArgs);
}
// then add the return value of the previous function.
callargs = callargs.concat(fnReturnValue);
// callargs, the parameters for the next function will have
// return value if previous function, original args
const that = this;
if (delay && delay > 0) {
setTimeout(() => {
that._callFunctions(...callargs);
}, delay);
} else {
// TODO: fix stackoverflow
that._callFunctions(...callargs);
}
};
//
const create = function (delay, functionArray, callback, ...args) {
const fchain = new Chain(delay, functionArray, callback);
fchain.setFunctionArgs(args);
return fchain;
};
//
module.exports = {create};
115 changes: 31 additions & 84 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,95 +1,42 @@
'use strict';
//
const Chain = function Chain (timeout, functionArray, callback) {
if (!(this instanceof Chain)) {
return new Chain(timeout, functionArray);
}
if (timeout) {
this.setTimeout(timeout);
}
if (functionArray) {
this.setFunctions(functionArray);
}
if (callback) {
this.setCallback(callback);
}
};
//
Chain.prototype.setTimeout = function (millis) {
this._timeout = millis;
};
//
Chain.prototype.setFunctionArgs = function (args) {
this._functionArgs = args;
};
//
Chain.prototype.setFunctions = function (functionArray) {
this._functionArray = functionArray;
};
//
Chain.prototype.setCallback = function (callback) {
this._callback = callback;
};
//
Chain.prototype.startCalls = function (...args) {
if (args && args.length > 0) {
this.setFunctionArgs(args);
}
return this._callFunctions(...[this._timeout, this._functionArray].concat(this._functionArgs));
};
const chain = require('./chain');
//
// functionArguments will have the return value from the previous function call
// and the original function arguments which was set or passed to startCalls function.
Chain.prototype._callFunctions = function (timeout, functions, ...args) {
// get arguments to the functiongs
if (!functions || functions.length === 0) {
// if there are no functions to invoke then callback
if (this._callback) {
this._callback.apply(this._callback, args);
}
return;
}
let retvalue = null;
const repeatFunction = function (actualFunction, continueCallback, ...args) {
let result = null;
try {
// invoke the function
retvalue = functions[0].apply(functions[0], args);
result = actualFunction(...args);
} catch (err) {
if (this._callback) {
this._callback.apply(this._callback, err);
if (continueCallback) {
// TODO: use the callback and decide to stop.
continueCallback(err, result);
}
return;
}
// remove the invoked function from the array
const nextFunctions = functions.slice(1);
// check if return value is another chain
if (retvalue && retvalue instanceof Chain && retvalue._functionArray && retvalue._functionArray[0]) {
// push the new chain's functions to the beginning of the original chain
nextFunctions.unshift(...retvalue._functionArray);
// replace function arguments
if (retvalue._functionArgs) {
retvalue = retvalue._functionArgs;
} else {
retvalue = args;
}
}
// prepare arguments for the next function call
let callargs = [timeout, nextFunctions];
// add the return value of the previous function first
if (retvalue) {
callargs = callargs.concat(retvalue);
}
// then add original arguments
if (this._functionArgs) {
callargs = callargs.concat(this._functionArgs);
let repeat = false;
if (continueCallback) {
repeat = continueCallback(null, result);
}
const that = this;
if (timeout && timeout > 0) {
setTimeout(() => {
that._callFunctions(...callargs);
}, timeout);
} else {
that._callFunctions(...callargs);
if (repeat) {
const fcc = chain.create();
fcc.setFunctions([repeatFunction]);
// args.unshift(actualFunction);
// fcc.setFunctionArgs([actualFunction, continueCallback, resultCallback].concat(result));
fcc.setFunctionArgs([result]);
return fcc;
}
return result;
};
//
module.exports = Chain;
const createRepeatFunctionChain = function (actualFunction, continueCallback, resultCallback, ...args) {
const fchain = chain.create(
-1, [repeatFunction], resultCallback,
actualFunction, continueCallback, ...args
);
return fchain;
};
//
module.exports = {
'create': chain.create,
createRepeatFunctionChain,
repeatFunction
};
Loading

0 comments on commit bd1cae0

Please sign in to comment.