@byte-this/funscript
Advanced tools
Comparing version
{ | ||
"name": "@byte-this/funscript", | ||
"version": "1.0.32", | ||
"version": "1.0.33", | ||
"description": "A typescript API which facilitates functional programming.", | ||
@@ -5,0 +5,0 @@ "main": "public-api.js", |
import { iCollectPendingInvocations } from "../models/collect-pending-invocations"; | ||
export declare const CollectPendingInvocations: iCollectPendingInvocations; | ||
export declare const AwaitAllCollections: () => Promise<unknown>; |
@@ -1,28 +0,112 @@ | ||
//import EventEmitter from "eventemitter3"; | ||
import EventEmitter from "events"; | ||
import { Clone } from "../clone/clone"; | ||
import { Equals } from "../equals/equals"; | ||
const eventEmitter = new EventEmitter(); | ||
const findPendingIndex = (func, ...params) => { | ||
return pending.findIndex((item) => item.func === func && Equals(params, [item.args])); | ||
}; | ||
const findPendingItem = (func, ...params) => { | ||
return pending.find((item) => item.func === func && Equals(params, [item.args])); | ||
}; | ||
const addPendingItem = (func, args, promise) => { | ||
pending.push({ | ||
func, | ||
args: args, | ||
promise, | ||
}); | ||
eventEmitter.emit("update", pending.length); | ||
}; | ||
const removePendingItem = (func, args) => { | ||
const finishedInd = findPendingIndex(func, args); | ||
if (finishedInd > -1) { | ||
pending.splice(finishedInd, 1); | ||
eventEmitter.emit("update", pending.length); | ||
// map pending function calls, function => params[] | ||
class ListNode { | ||
constructor(value) { | ||
this.value = value; | ||
this.next = null; | ||
} | ||
}; | ||
const pending = []; | ||
} | ||
class ArgsLinkedList { | ||
constructor(pending) { | ||
this.head = null; | ||
this.head = new ListNode(pending); | ||
} | ||
findInList(args) { | ||
let node = this.head; | ||
while (node) { | ||
if (Equals(node.value.args, args)) { | ||
return node.value; | ||
} | ||
node = node.next; | ||
} | ||
return null; | ||
} | ||
addToList(pending) { | ||
const newNode = new ListNode(pending); | ||
newNode.next = this.head; | ||
this.head = newNode; | ||
} | ||
deleteFromList(args) { | ||
let prevNode = null; | ||
let node = this.head; | ||
while (node) { | ||
if (Equals(node.value.args, args)) { | ||
if (prevNode) { | ||
prevNode.next = node.next; | ||
return { | ||
itemRemoved: true, | ||
listIsEmpty: false | ||
}; | ||
} | ||
else if (!node.next) { | ||
this.head = null; | ||
return { | ||
itemRemoved: true, | ||
listIsEmpty: true | ||
}; | ||
} | ||
else { | ||
this.head = node.next; | ||
return { | ||
itemRemoved: true, | ||
listIsEmpty: false | ||
}; | ||
} | ||
} | ||
prevNode = node; | ||
node = node.next; | ||
} | ||
return { | ||
itemRemoved: false, | ||
listIsEmpty: false | ||
}; | ||
} | ||
} | ||
class PendingCallsContainer { | ||
constructor() { | ||
this.funcMap = new Map(); | ||
this.size = 0; | ||
} | ||
findPendingItem(func, params) { | ||
const argList = this.funcMap.get(func); | ||
if (!argList) { | ||
return void 0; | ||
} | ||
const pendingArgs = argList.findInList(params); | ||
if (!pendingArgs) { | ||
return void 0; | ||
} | ||
return { | ||
func, | ||
...pendingArgs | ||
}; | ||
} | ||
addPendingItem(func, args, promise) { | ||
if (!this.funcMap.has(func)) { | ||
this.funcMap.set(func, new ArgsLinkedList({ args, promise })); | ||
} | ||
else { | ||
this.funcMap.get(func).addToList({ args, promise }); | ||
} | ||
this.size++; | ||
if (this.size > 1000) { | ||
console.log("DEBUG issue"); | ||
} | ||
} | ||
removePendingItem(func, args) { | ||
const funcPending = this.funcMap.get(func); | ||
if (!funcPending) { | ||
return; | ||
} | ||
const { itemRemoved, listIsEmpty } = funcPending.deleteFromList(args); | ||
if (itemRemoved) { | ||
this.size--; | ||
} | ||
if (listIsEmpty) { | ||
this.funcMap.delete(func); | ||
} | ||
} | ||
} | ||
const pendingCollection = new PendingCallsContainer(); | ||
export const CollectPendingInvocations = (func) => { | ||
@@ -34,3 +118,3 @@ const decorated = function (...params) { | ||
const clonedParams = Clone(params); | ||
const pendingItem = findPendingItem(func, params); | ||
const pendingItem = pendingCollection.findPendingItem(func, params); | ||
if (pendingItem) { | ||
@@ -41,7 +125,7 @@ return pendingItem.promise; | ||
const promise = func.apply(me, clonedParams); | ||
addPendingItem(func, clonedParams, promise); | ||
pendingCollection.addPendingItem(func, clonedParams, promise); | ||
promise | ||
.catch(() => { }) | ||
.finally(() => { | ||
removePendingItem(func, clonedParams); | ||
pendingCollection.removePendingItem(func, clonedParams); | ||
}); | ||
@@ -58,14 +142,1 @@ return promise; | ||
}; | ||
//useful for unit test purposes | ||
export const AwaitAllCollections = () => { | ||
if (pending.length === 0) { | ||
return Promise.resolve(void 0); | ||
} | ||
return new Promise((resolve) => { | ||
eventEmitter.on("update", (len) => { | ||
if (len === 0) { | ||
resolve(void 0); | ||
} | ||
}); | ||
}); | ||
}; |
@@ -23,2 +23,18 @@ import { Compose } from "../compose/compose"; | ||
/** | ||
* Shuffle an array in place | ||
*/ | ||
const shuffleInPlace = (array) => { | ||
let currentIndex = array.length, randomIndex; | ||
// While there remain elements to shuffle... | ||
while (currentIndex != 0) { | ||
// Pick a remaining element... | ||
randomIndex = Math.floor(Math.random() * currentIndex); | ||
currentIndex--; | ||
// And swap it with the current element. | ||
[array[currentIndex], array[randomIndex]] = [ | ||
array[randomIndex], array[currentIndex] | ||
]; | ||
} | ||
}; | ||
/** | ||
* Object which will hold async versions of array methods | ||
@@ -276,2 +292,14 @@ */ | ||
}, | ||
/** | ||
* Shuffle an array in place | ||
*/ | ||
shuffleInPlace, | ||
/** | ||
* Make a copy of an array and shuffle the copy | ||
*/ | ||
shuffle: (input) => { | ||
const clone = [...input]; | ||
shuffleInPlace(clone); | ||
return clone; | ||
} | ||
}; |
@@ -35,2 +35,4 @@ export declare type ArMapAsyncCallback<InputT, OutputT> = (element: InputT, index?: number, array?: InputT[]) => OutputT | Promise<OutputT>; | ||
uniqueValues<T>(input: T[], eq?: (a: T, b: T) => boolean): T[]; | ||
shuffleInPlace<T>(input: T[]): void; | ||
shuffle<T>(input: T[]): T[]; | ||
} |
280166
0.97%3208
3.22%