diff --git a/src/controller/ApplicationController.tsx b/src/controller/ApplicationController.tsx index 45b1acc..79542e5 100644 --- a/src/controller/ApplicationController.tsx +++ b/src/controller/ApplicationController.tsx @@ -12,6 +12,7 @@ import Debug from 'debug'; import { randomId } from '../utils/randomId'; import CAF from 'caf'; import { cloneDeep } from 'lodash'; +import { observe } from '..'; const debug = Debug('framework:controller'); @@ -30,6 +31,8 @@ type GetControllerConstructor = { new (): T }; type GetControllerProps> = T extends ApplicationControllerConstructor ? P : never; +export type DependencyCallback = () => void | Promise; + /** * General rules to follow for using controllers: * @@ -162,6 +165,34 @@ class ApplicationController< */ internalDestroy() { this.destroy(); + this.deferredDestroyCallbacks.forEach(([_name, callback]) => callback()); + this.deferredDestroyCallbacks = []; + } + + private deferredDestroyCallbacks: [string, DependencyCallback][] = []; + + resolveDependency(name: string) { + const callbacks = this.deferredDestroyCallbacks.filter(([n]) => n === name); + callbacks.forEach(([_, callback]) => callback()); + this.deferredDestroyCallbacks = this.deferredDestroyCallbacks.filter(([n]) => n !== name); + } + + addDependency(name: string, callback: DependencyCallback): void; + addDependency(callback: DependencyCallback): void; + addDependency(nameOrCallback: string | DependencyCallback, callback?: DependencyCallback) { + if (typeof nameOrCallback === "string") { + if (!callback) throw new Error("Callback is required"); + this.deferredDestroyCallbacks.push([nameOrCallback, callback]); + } else if (typeof nameOrCallback === "function") { + this.deferredDestroyCallbacks.push(["unknown", nameOrCallback]); + } else { + throw new Error("Invalid arguments"); + } + } + + observe(callback: () => void, options: Parameters[1] = {}) { + const observer = observe(callback, options); + this.addDependency(() => observer()); } /**