Skip to content

Instantly share code, notes, and snippets.

@vlas-ilya
Last active August 5, 2021 12:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vlas-ilya/635fa97bf9b1d15065869618a314b415 to your computer and use it in GitHub Desktop.
Save vlas-ilya/635fa97bf9b1d15065869618a314b415 to your computer and use it in GitHub Desktop.
type Supplier<T> = () => T;
type Value<T> = T;
type SupplierOnValue<T> = Supplier<T> | Value<T>;
type Closable = { close(): Promise<void> };
type ClosableCreator<T> = SupplierOnValue<Promise<T>>;
type Use = <C extends Closable>(closableCreator: ClosableCreator<C>) => Promise<C>;
type Runnable<Result> = (use: Use) => Promise<Result>;
type ClosableSync = { close(): void };
type ClosableCreatorSync<T> = SupplierOnValue<T>;
type UseSync = <C extends Closable>(closableCreator: ClosableCreatorSync<C>) => C;
type RunnableSync<Result> = (use: UseSync) => Result
async function closableManager<Result>(runnable: Runnable<Result>): Promise<Result> {
const listOfClosable: Closable[] = [];
async function use<C extends Closable>(closableCreator: ClosableCreator<C>): Promise<C> {
let closable = typeof closableCreator === "function"
? await closableCreator()
: await closableCreator;
listOfClosable.push(closable);
return closable;
}
const result = await runnable(use);
await Promise.all(listOfClosable
.filter(closable => typeof closable.close === "function")
.map(closable => closable.close()));
return result;
}
function closableManagerSync<Result>(runnable: RunnableSync<Result>): Result {
const listOfClosable: Closable[] = [];
function use<C extends Closable>(closableCreator: ClosableCreatorSync<C>): C {
const closable = typeof closableCreator === "function"
? closableCreator()
: closableCreator;
listOfClosable.push(closable);
return closable;
}
const result = runnable(use);
listOfClosable
.filter(closable => typeof closable.close === "function")
.map(closable => closable.close())
return result;
}
console.log("Test");
class A implements Closable {
constructor() {
console.log("A created");
}
run() {
console.log("A.run runned");
return "A";
}
async close() {
console.log("A.close runned");
}
}
class B implements Closable {
constructor() {
console.log("B created");
}
run() {
console.log("B.run runned");
return "B";
}
async close() {
console.log("B.close runned");
}
}
class C implements Closable {
constructor() {
console.log("C created");
}
run() {
console.log("C.run runned");
return "C";
}
async close() {
console.log("C.close runned");
}
}
console.log("Test Sync");
const result = closableManagerSync(use => {
const a = use<A>(() => new A());
const b = use<B>(new B());
const c = use<C>(() => new C());
return a.run() + b.run() + c.run();
});
console.log(result);
console.log("Test Promise");
closableManager(async use => {
const a = await use<A>(async () => new A());
const b = await use<B>(Promise.resolve(new B()));
const c = await use<C>(async () => new C());
return a.run() + b.run() + c.run();
}).then(result => console.log(result));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment