callback-utility
Version:
An utility handler to deal with callback functions
338 lines • 14.9 kB
JavaScript
import { CallTypes } from "./calls-struct.js";
import { FunctionResult, InternalResult } from "./result.js";
import { CBException, CBExceptions } from "./exception.js";
export class CB {
static PREVIOUS_ERROR = Symbol("PREVIOUS_ERROR");
static PREVIOUS_RESULT1 = Symbol("PREVIOUS_RESULT1");
static PREVIOUS_RESULT2 = Symbol("PREVIOUS_RESULT2");
static PREVIOUS_RESULT3 = Symbol("PREVIOUS_RESULT3");
static PREVIOUS_RESULT4 = Symbol("PREVIOUS_RESULT4");
static PREVIOUS_RESULT5 = Symbol("PREVIOUS_RESULT5");
static PREVIOUS_RESULT6 = Symbol("PREVIOUS_RESULT6");
static PREVIOUS_RESULT7 = Symbol("PREVIOUS_RESULT7");
static PREVIOUS_RESULT8 = Symbol("PREVIOUS_RESULT8");
static PREVIOUS_RESULT9 = Symbol("PREVIOUS_RESULT9");
static #_Tokens = [
CB.PREVIOUS_ERROR,
CB.PREVIOUS_RESULT1,
CB.PREVIOUS_RESULT2,
CB.PREVIOUS_RESULT3,
CB.PREVIOUS_RESULT4,
CB.PREVIOUS_RESULT5,
CB.PREVIOUS_RESULT6,
CB.PREVIOUS_RESULT7,
CB.PREVIOUS_RESULT8,
CB.PREVIOUS_RESULT9,
];
static f(p_Param1, p_Param2, ...p_Args) {
let strAlias;
let fnCall;
let arrArgs;
let blnToken = false;
if ("string" === typeof p_Param1) {
strAlias = p_Param1;
fnCall = p_Param2;
arrArgs = [...p_Args];
}
else {
strAlias = "";
fnCall = p_Param1;
arrArgs = [p_Param2, ...p_Args];
}
if (p_Args.length > 0 &&
p_Args.some(varArg => CB.#_Tokens.includes(varArg))) {
blnToken = true;
}
return {
Type: CallTypes.Function,
Alias: strAlias,
Fn: fnCall,
Args: arrArgs,
Finished: false,
Invoked: false,
Parent: null,
Next: null,
Previous: null,
Root: null,
RootIndex: -1,
ParentIndex: -1,
UseToken: blnToken,
TsStart: 0,
TsFinish: 0
};
}
static p(p_Param1, ...p_ExecStructs) {
let strAlias;
let arrStructs;
if ("string" === typeof p_Param1) {
strAlias = p_Param1;
arrStructs = [...p_ExecStructs];
}
else {
strAlias = "";
arrStructs = [p_Param1, ...p_ExecStructs];
}
const structParallel = {
Alias: strAlias,
Type: CallTypes.Parallel,
Calls: arrStructs,
CallQty: 0,
CallCount: 0,
Finished: false,
Invoked: false,
Parent: null,
Next: null,
Previous: null,
Root: null,
ParentIndex: -1,
RootIndex: -1,
TsStart: 0,
TsFinish: 0
};
for (let structCall of structParallel.Calls) {
structCall.Parent = structParallel;
if (structCall.UseToken)
throw new CBException(CBExceptions.TokenInParallelCall);
}
return structParallel;
}
static e(p_CallStruct, p_Param2, p_Param3, p_Param4, p_Param5) {
let fnCallback, blnBreakOnError = true, blnStats = false, intTimeout = 0;
try {
if ("function" === typeof p_Param2)
fnCallback = p_Param2;
else if ("number" === typeof p_Param2) {
intTimeout = p_Param2;
if ("function" === typeof p_Param3)
fnCallback = p_Param3;
else if ("boolean" === typeof p_Param3) {
blnBreakOnError = p_Param3;
if ("function" === typeof p_Param4)
fnCallback = p_Param4;
else if ("boolean" === typeof p_Param4) {
blnStats = p_Param4;
if ("function" === typeof p_Param5)
fnCallback = p_Param5;
}
}
}
if (intTimeout <= 0)
intTimeout = 5000;
if (p_CallStruct.Type !== CallTypes.Parallel &&
p_CallStruct.Type !== CallTypes.Sequential)
throw new CBException(CBExceptions.InvalidStructToExecute);
const structRoot = p_CallStruct;
let intCalls = -1;
structRoot.PlainCalls = [];
structRoot.GetStats = blnStats;
const fnSetRoot = function (p_Root, p_CallStructSetRoot) {
if (!p_CallStructSetRoot)
p_CallStructSetRoot = p_Root;
structRoot.PlainCalls.push(p_CallStructSetRoot);
p_CallStructSetRoot.RootIndex = ++intCalls;
p_CallStructSetRoot.Root = p_Root;
if (p_CallStructSetRoot.Type === CallTypes.Parallel ||
p_CallStructSetRoot.Type === CallTypes.Sequential) {
for (let structCallSetRoot of p_CallStructSetRoot.Calls) {
fnSetRoot(p_Root, structCallSetRoot);
}
}
};
fnSetRoot(p_CallStruct);
const prmsReturn = new Promise((resolve, reject) => {
const onFinish = (p_Exception) => {
structRoot.Break = true;
if (p_Exception)
reject(p_Exception);
else
resolve(structRoot.MainResult.GetResult());
};
structRoot.MainResult = new InternalResult(structRoot, intTimeout, blnBreakOnError, blnStats, onFinish);
CB.#Invoke(p_CallStruct);
});
if (!fnCallback)
return prmsReturn;
else
prmsReturn
.then(value => fnCallback(value.error, value.timeout, value))
.catch(error => fnCallback(error));
}
catch (p_Exception) {
const excptUnknow = p_Exception instanceof CBException ?
p_Exception :
new CBException(CBExceptions.InternalError, p_Exception);
if (!fnCallback)
throw excptUnknow;
else
fnCallback(excptUnknow);
}
}
static s(p_Param1, ...p_Fns) {
let strAlias;
let arrStructs;
if ("string" === typeof p_Param1) {
strAlias = p_Param1;
arrStructs = [...p_Fns];
}
else {
strAlias = "";
arrStructs = [p_Param1, ...p_Fns];
}
const structSequential = {
Alias: strAlias,
Type: CallTypes.Sequential,
CallCount: 0,
CallQty: 0,
Calls: arrStructs,
Finished: false,
Invoked: false,
Parent: null,
Next: null,
Previous: null,
Root: null,
ParentIndex: -1,
RootIndex: -1,
TsStart: 0,
TsFinish: 0
};
for (let intA = 0; intA < structSequential.Calls.length; intA++) {
const structCall = structSequential.Calls[intA];
if (intA === 0 && structCall.UseToken)
throw new CBException(CBExceptions.TokenInFirstCall);
structCall.Parent = structSequential;
if (intA < structSequential.Calls.length - 1)
structCall.Next = structSequential.Calls[intA + 1];
if (intA > 0)
structCall.Previous = structSequential.Calls[intA - 1];
}
return structSequential;
}
static #Invoke(p_Call) {
const objRoot = p_Call.Root;
const objResult = p_Call.Root.MainResult;
if (objRoot.Break)
return;
if (objRoot.GetStats)
p_Call.TsStart = Date.now();
if (p_Call.Parent)
p_Call.ParentIndex = p_Call.Parent.CallQty++;
const fnCallback = function () {
if (objRoot.Break)
return;
if (objRoot.GetStats)
p_Call.TsFinish = Date.now();
const structCallCallback = p_Call;
if (!structCallCallback.Exception)
objResult.SetResult(structCallCallback.RootIndex, structCallCallback.Alias, arguments[0], structCallCallback.TsStart, structCallCallback.TsFinish, Array.prototype.slice.call(arguments, 1));
else
objResult.SetException(p_Call.RootIndex, p_Call.Alias, p_Call.Exception);
const fnFinishCall = (p_FinishCall) => {
p_FinishCall.Finished = true;
if (p_FinishCall.Parent) {
p_FinishCall.Parent.CallCount++;
if (p_FinishCall.Parent.CallCount === p_FinishCall.Parent.Calls.length)
fnFinishCall(p_FinishCall.Parent);
}
};
fnFinishCall(p_Call);
if (p_Call.Next)
CB.#Invoke(p_Call.Next);
else if (p_Call.Parent.Next && p_Call.Parent.Finished)
CB.#Invoke(p_Call.Parent.Next);
};
switch (p_Call.Type) {
case CallTypes.Function:
setImmediate(() => {
try {
if (p_Call.Parent.Type === CallTypes.Sequential &&
p_Call.UseToken) {
for (let intA = 0; intA < p_Call.Args.length; intA++) {
const varArg = p_Call.Args[intA];
let intResult = -1, blnError = false;
if ("symbol" === typeof varArg) {
switch (varArg) {
case CB.PREVIOUS_ERROR:
blnError = true;
break;
case CB.PREVIOUS_RESULT1:
intResult = 0;
break;
case CB.PREVIOUS_RESULT2:
intResult = 1;
break;
case CB.PREVIOUS_RESULT3:
intResult = 2;
break;
case CB.PREVIOUS_RESULT4:
intResult = 3;
break;
case CB.PREVIOUS_RESULT5:
intResult = 4;
break;
case CB.PREVIOUS_RESULT6:
intResult = 5;
break;
case CB.PREVIOUS_RESULT7:
intResult = 6;
break;
case CB.PREVIOUS_RESULT8:
intResult = 7;
break;
case CB.PREVIOUS_RESULT9:
intResult = 8;
break;
}
if (blnError)
p_Call.Args[intA] = objResult[p_Call.Previous.RootIndex].error;
else if (intResult > -1) {
if (p_Call.Previous.Type === CallTypes.Function) {
if ("undefined" === typeof objResult[p_Call.Previous.RootIndex].results[intResult])
throw new CBException(CBExceptions.InvalidTokenResult);
p_Call.Args[intA] = objResult[p_Call.Previous.RootIndex].results[intResult];
}
else {
const arrPreviousResults = objResult[p_Call.Previous.RootIndex].results;
const arrFilteredResults = [];
const fnGetResults = (p_Results, p_ResultsFiltered, p_Struct) => {
for (let intA = 0; intA < p_Struct.length; intA++) {
if (!Array.isArray(p_Results[intA]) ||
p_Results[intA].length < (intResult + 1))
return new CBException(CBExceptions.InvalidTokenResult);
if (p_Struct[intA] instanceof FunctionResult)
p_ResultsFiltered[intA] = p_Results[intA][intResult];
else {
p_ResultsFiltered[intA] = [];
return fnGetResults(p_Results[intA], p_ResultsFiltered[intA], p_Struct[intA]);
}
}
};
const errGetResultsReturn = fnGetResults(arrPreviousResults, arrFilteredResults, objResult[p_Call.Previous.RootIndex]);
if (errGetResultsReturn)
throw errGetResultsReturn;
p_Call.Args[intA] = arrFilteredResults;
}
}
}
}
}
p_Call.Fn(...p_Call.Args, fnCallback);
}
catch (p_Exception) {
p_Call.Exception = p_Exception;
fnCallback();
}
});
break;
case CallTypes.Parallel:
for (let call of p_Call.Calls) {
CB.#Invoke(call);
}
break;
case CallTypes.Sequential:
CB.#Invoke(p_Call.Calls[0]);
break;
}
p_Call.Invoked = true;
}
}
//# sourceMappingURL=callback-handler.js.map