/** ***************************************** * Created by edonet@163.com * Created on 2021-03-22 23:22:14 ***************************************** */ 'use strict'; /** ***************************************** * 加载依赖 ***************************************** */ import { proxy } from './proxy'; /** ***************************************** * 状态 ***************************************** */ interface State { [key: string]: unknown; } /** ***************************************** * 状态 ***************************************** */ type Context = T & { next: () => void | P }; /** ***************************************** * 事件函数 ***************************************** */ type Handler = (context: Context) => void | P; /** ***************************************** * 事件对象 ***************************************** */ interface Node { handler: Handler; prev: Node; next?: Node; } /** ***************************************** * 洋葱对象 ***************************************** */ export class Onion { /** 链头 */ private $$onionHead!: Node; /** 链尾 */ private $$onionTail!: Node; /** 初始化对象 */ public constructor() { // 定义链头 Object.defineProperty(this, '$$onionHead', { configurable: false, enumerable: false, writable: true, value: {}, }); // 定义链尾 Object.defineProperty(this, '$$onionTail', { configurable: false, enumerable: false, writable: true, value: this.$$onionHead, }); } /** 添加处理函数 */ public add(handler: Handler): () => void { // 校验参数 if (typeof handler !== 'function') { throw new Error('expect handler to be a function!'); } // 创建节点 const ob: Node = { handler, prev: this.$$onionTail }; // 添加订阅 this.$$onionTail.next = ob; this.$$onionTail = ob; // 返回取消函数 return () => { const node = ob as Partial>; // 移除节点 if (ob.next) { ob.prev.next = ob.next; ob.next.prev = ob.prev; } else { ob.prev.next = undefined; this.$$onionTail = ob.prev; } // 清空节点属性 node.handler = undefined; node.prev = undefined; node.next = undefined; }; } /** 执行处理函数 */ public call(state: T, callback?: (state: T) => void | P): void | P { const proto = proxy(state || null); // 执行步骤 const invoke = (node: Node): void | P => { const next = node.next; // 没有下一节点,到达链尾 if (!next) { return callback?.(state); } // 创建上下文 const context = Object.create(proto); // 添加下一步 context.next = () => invoke(next); // 执行回调 return next.handler(context); }; // 开始执行 return invoke(this.$$onionHead); } /** 清空链 */ public clear(): void { let node = this.$$onionHead; // 遍历节点 while (node && node !== this.$$onionTail) { const ob = node as Partial>; // 更新节点 node = node.next as Node; // 删除信息 ob.handler = undefined; ob.prev = undefined; ob.next = undefined; } // 重置链尾 this.$$onionTail = this.$$onionHead; } } /** ***************************************** * 创建洋葱对象 ***************************************** */ export function onion(): Onion { return new Onion(); }