UNPKG

@vitarx/responsive

Version:
241 lines (240 loc) 6.2 kB
/** * Effect类提供了一个通用的副作用管理实现 * * 该类设计用于管理具有生命周期的副作用操作,提供了: * - 状态管理:支持active(活跃)、paused(暂停)和deprecated(弃用)三种状态 * - 生命周期钩子:可监听销毁(dispose)、暂停(pause)和恢复(resume)事件 * - 错误处理:统一的错误捕获和处理机制 * * 主要应用场景: * - 资源管理:管理需要及时清理的资源(如定时器、事件监听器等) * - 状态同步:协调多个相关联的副作用操作 * - 可中断任务:支持暂停和恢复的长期运行任务 * * @template ErrorSource - 错误源类型 */ export class Effect { constructor() { /** * 回调函数集合 * * @protected */ Object.defineProperty(this, "callbacks", { enumerable: true, configurable: true, writable: true, value: void 0 }); /** * 状态 * * @protected */ Object.defineProperty(this, "_state", { enumerable: true, configurable: true, writable: true, value: 'active' }); } /** * 状态: * - `active`: 活跃 * - `paused`: 暂停 * - `deprecated`: 弃用 */ get state() { return this._state; } /** * 是否已弃用/销毁 * * @readonly */ get isDeprecated() { return this.state === 'deprecated'; } /** * 判断是否为暂停状态 */ get isPaused() { return this.state === 'paused'; } /** * 判断是否处于活跃状态 */ get isActive() { return this.state === 'active'; } /** * 状态: * - `active`: 活跃 * - `paused`: 暂停 * - `deprecated`: 弃用 */ getState() { return this._state; } /** * @inheritDoc */ dispose() { if (this.isDeprecated) return true; this._state = 'deprecated'; this.triggerCallback('dispose'); this.clearCallbacks(); return true; } /** * @inheritDoc */ onDispose(callback) { return this.addCallback(callback, 'dispose'); } /** * @inheritDoc */ pause() { if (!this.isActive) { throw new Error('Effect must be active to pause.'); } this._state = 'paused'; this.triggerCallback('pause'); return true; } /** * @inheritDoc */ resume() { if (!this.isPaused) { throw new Error('Effect must be paused to resume.'); } this._state = 'active'; this.triggerCallback('resume'); return true; } /** * 监听暂停事件 * * @param {VoidCallback} callback - 回调函数 * @returns {this} */ onPause(callback) { return this.addCallback(callback, 'pause'); } /** * 监听恢复事件 * * @param {VoidCallback} callback - 回调函数 * @returns {this} */ onResume(callback) { return this.addCallback(callback, 'resume'); } /** * 监听错误事件 * * @param {EffectCallbackErrorHandler} callback - 回调函数 * @returns {this} */ onError(callback) { return this.addCallback(callback, 'error'); } /** * 清理所有回调函数 * * @private */ clearCallbacks() { if (this.callbacks) { this.callbacks.clear(); this.callbacks = undefined; } } /** * 报告回调异常 * * @param {unknown} e - 捕获到的异常 * @param {EffectInherentErrorSource} source - 回调事件源 * @protected */ reportError(e, source) { const errorHandlers = this.callbacks?.get('error'); if (errorHandlers) { errorHandlers.forEach(callback => { try { callback(e, source); } catch (innerError) { console.error(`Error handler for "${source}" threw an error:`, innerError); } }); } else { console.error(`Unhandled error in effect callback (${source}):`, e); } } /** * 触发回调 * * @param type * @protected */ triggerCallback(type) { const callbacks = this.callbacks?.get(type); if (!callbacks) return; callbacks.forEach(callback => { try { callback(); } catch (e) { this.reportError(e, type); } }); } /** * 添加回调函数 * * @param callback * @param type * @private */ addCallback(callback, type) { if (this.isDeprecated) { throw new Error('Cannot add callback to a deprecated effect.'); } if (typeof callback !== 'function') { throw new TypeError(`Callback parameter for "${type}" must be a function.`); } if (!this.callbacks) { this.callbacks = new Map(); } const callbackSet = this.callbacks.get(type) || new Set(); callbackSet.add(callback); this.callbacks.set(type, callbackSet); return this; } } /** * 检测是否为可处置副作用对象 * * @param {any} obj - 要检测的对象 * @returns {boolean} 如果对象实现了 EffectInterface,则返回 true,否则返回 false */ export const isEffect = (obj) => { if (!obj || typeof obj !== 'object') return false; if (obj instanceof Effect) return true; return (typeof obj.dispose === 'function' && typeof obj.onDispose === 'function' && typeof obj.pause === 'function' && typeof obj.onPause === 'function' && typeof obj.resume === 'function' && typeof obj.onResume === 'function' && typeof obj.onError === 'function' && typeof obj.getState === 'function'); };