First Commit
This commit is contained in:
commit
7fed9fc8de
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules/
|
||||||
|
lib/
|
2
.npmingore
Normal file
2
.npmingore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
src/
|
||||||
|
node_modules/
|
14
package-lock.json
generated
Normal file
14
package-lock.json
generated
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "@hibas123/utils",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"typescript": {
|
||||||
|
"version": "3.3.3333",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3333.tgz",
|
||||||
|
"integrity": "sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
package.json
Normal file
21
package.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "@hibas123/utils",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Different Utilities, that are not worth own packages",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"types": "lib/index.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"prepublishOnly": "tsc",
|
||||||
|
"build": "tsc",
|
||||||
|
"watch-ts": "tsc -w"
|
||||||
|
},
|
||||||
|
"author": "Fabian Stamm <dev@fabianstamm.de>",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"url": "https://git.stamm.me/OpenServer/Utils.git",
|
||||||
|
"type": "git"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^3.3.3333"
|
||||||
|
}
|
||||||
|
}
|
57
readme.md
Normal file
57
readme.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# Utils
|
||||||
|
|
||||||
|
The utils only use standard JavaScript, so they can be used in Browser and NodeJS.
|
||||||
|
|
||||||
|
Also they are very small. Uncompressed and unminified only 3kb.
|
||||||
|
|
||||||
|
The utils have TypeScript definitions and are compatible with ES2015.
|
||||||
|
|
||||||
|
## Lock
|
||||||
|
|
||||||
|
Lock is a very simple promise based Locking mechanism for JavaScript.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
``` typescript
|
||||||
|
import { Lock } from "@hibas123/utils";
|
||||||
|
|
||||||
|
const lock = new Lock();
|
||||||
|
|
||||||
|
async doThingThatNeedsLocking() {
|
||||||
|
let release = await lock.getLock(); // This will wait till lock from others is released
|
||||||
|
|
||||||
|
// Do stuff that requires lock
|
||||||
|
|
||||||
|
release(); // Release lock
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Observable
|
||||||
|
|
||||||
|
Very simple and light weight Observable.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
``` typescript
|
||||||
|
import { Observable } from "@hibas123/util";
|
||||||
|
|
||||||
|
const server = new Observable(); // Get new Observable Server
|
||||||
|
|
||||||
|
// Server can only send, not subscribe to messages
|
||||||
|
// Receiving is only possible via the public API
|
||||||
|
const public = server.getPublicApi();
|
||||||
|
|
||||||
|
const func = (data)=>{
|
||||||
|
console.log(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// func will be callen when a message is available
|
||||||
|
public.subscribe(func);
|
||||||
|
|
||||||
|
server.send("Hello World");
|
||||||
|
|
||||||
|
// This will unsubscribe the function. Please note, that it can
|
||||||
|
// only unsubscribe the exact function, that is used in subscribe
|
||||||
|
public.unsubscribe(func);
|
||||||
|
|
||||||
|
// This now won't call func anymore
|
||||||
|
server.send("Hello World2");
|
||||||
|
```
|
9
src/index.ts
Normal file
9
src/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import Lock, { Release } from "./lock";
|
||||||
|
import Observable, { ObserverCallback } from "./observable";
|
||||||
|
|
||||||
|
export {
|
||||||
|
Lock,
|
||||||
|
Release,
|
||||||
|
Observable,
|
||||||
|
ObserverCallback
|
||||||
|
}
|
53
src/lock.ts
Executable file
53
src/lock.ts
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
export type Release = { release: () => void };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic Locking mechanism for JavaScript
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export default class Lock {
|
||||||
|
private _locked: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the state of the Locken
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
get locked(): boolean {
|
||||||
|
return this._locked;
|
||||||
|
}
|
||||||
|
private toCome: (() => void)[] = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.release = this.release.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits till lock is free and returns a release function
|
||||||
|
*
|
||||||
|
* @return {function}
|
||||||
|
*/
|
||||||
|
async getLock(): Promise<Release> {
|
||||||
|
if (!this._locked) return { release: this.lock() };
|
||||||
|
else {
|
||||||
|
return new Promise<Release>((resolve) => {
|
||||||
|
this.toCome.push(() => {
|
||||||
|
resolve({ release: this.lock() });
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lock() {
|
||||||
|
this._locked = true;
|
||||||
|
return this.release;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async release() {
|
||||||
|
let next = this.toCome.shift();
|
||||||
|
if (next) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
this._locked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
src/observable.ts
Executable file
63
src/observable.ts
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
export type ObserverCallback<T> = (data: T[]) => void;
|
||||||
|
|
||||||
|
export default class Observable<T = any> {
|
||||||
|
private subscriber: { callback: ObserverCallback<T>, one: boolean }[] = [];
|
||||||
|
private events: T[] = [];
|
||||||
|
private timeout: number | undefined = undefined;
|
||||||
|
|
||||||
|
constructor(private collect: boolean = true, private collect_intervall: number = 100) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates Public API with subscribe and unsubscribe
|
||||||
|
*
|
||||||
|
* @returns {object}
|
||||||
|
*/
|
||||||
|
getPublicApi() {
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Subscribe to Observable
|
||||||
|
* @param {function} callback
|
||||||
|
*/
|
||||||
|
subscribe: (callback: ObserverCallback<T>, one: boolean = false) => {
|
||||||
|
let oldcb = this.subscriber.find(e => e.callback === callback);
|
||||||
|
if (oldcb)
|
||||||
|
oldcb.one = one
|
||||||
|
else
|
||||||
|
this.subscriber.push({ callback, one })
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Subscribe fron Observable
|
||||||
|
* @param {function} callback
|
||||||
|
*/
|
||||||
|
unsubscribe: (callback: ObserverCallback<T>) => {
|
||||||
|
let idx = this.subscriber.findIndex(e => e.callback === callback);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.subscriber.splice(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends data to all subscribers
|
||||||
|
* @param data data to be sent
|
||||||
|
*/
|
||||||
|
send(data: T) {
|
||||||
|
if (!this.collect)
|
||||||
|
this.subscriber.forEach(e => e.callback([data]));
|
||||||
|
else {
|
||||||
|
this.events.push(data);
|
||||||
|
if (!this.timeout) {
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
this.subscriber.forEach(cb => {
|
||||||
|
if (cb.one)
|
||||||
|
this.events.forEach(e => cb.callback([e]));
|
||||||
|
else
|
||||||
|
cb.callback(this.events)
|
||||||
|
});
|
||||||
|
this.timeout = undefined;
|
||||||
|
}, this.collect_intervall);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
tsconfig.json
Normal file
13
tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2015",
|
||||||
|
"module": "commonjs",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"outDir": "lib",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"preserveWatchOutput": true,
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user