UNPKG

@vitarx/responsive

Version:
214 lines (213 loc) 9.08 kB
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var _a, _Context_store; import { isArray, isFunction, isPromise } from '@vitarx/utils'; /** * 上下文管理器类,用于管理应用程序中的上下文状态 * * 该类提供了静态方法来设置、获取和管理上下文状态,支持同步和异步操作 * 上下文通过标签(Tag)进行标识,可以是字符串或Symbol * 注意:所有方法都是静态的,不需要实例化此类 */ export class Context { /** * 获取当前上下文仓库的只读视图 * * @readonly * @returns {ReadonlyMap<Tag, object>} 当前所有上下文的只读Map * @warning 注意:不要直接修改返回的Map,否则会破坏上下文管理器的状态 */ static get store() { return __classPrivateFieldGet(this, _a, "f", _Context_store); } /** * 获取当前存储的上下文数量 * * @readonly * @returns {number} 当前存储的上下文数量 */ static get size() { return __classPrivateFieldGet(this, _a, "f", _Context_store).size; } /** * 获取当前所有活跃上下文标签的迭代器 * * @readonly * @returns {MapIterator<Tag>} 当前所有上下文标签的迭代器 */ static get tags() { return __classPrivateFieldGet(this, _a, "f", _Context_store).keys(); } /** * 根据标签获取对应的上下文对象 * * @template T - 上下文对象的类型 * @param {Tag} tag - 要获取的上下文标签 * @returns {T|undefined} 找到的上下文对象,如果不存在则返回undefined */ static get(tag) { return __classPrivateFieldGet(this, _a, "f", _Context_store).get(tag); } /** * 卸载指定标签的上下文 * * @param {Tag} tag - 要卸载的上下文标签 * @param {object} [ctx] - 可选的要卸载的上下文对象,如果传入会严格对比 * @returns {boolean} 是否卸载成功 * * @description * 1. 如果只传入tag参数,则直接删除该标签对应的上下文 * 2. 如果同时传入tag和ctx参数,则只有在当前上下文与传入的ctx严格相等时才会删除 * 3. 返回值说明: * - 仅传入tag时总是返回true * - 同时传入tag和ctx时,只有在成功删除时返回true */ static unset(tag, ctx) { if (ctx) { if (!__classPrivateFieldGet(this, _a, "f", _Context_store).has(tag)) return true; const current = __classPrivateFieldGet(this, _a, "f", _Context_store).get(tag); if (current === ctx) { return __classPrivateFieldGet(this, _a, "f", _Context_store).delete(tag); } return false; } __classPrivateFieldGet(this, _a, "f", _Context_store).delete(tag); return true; } /** * 在指定上下文中运行一个函数 * * @template R - 函数返回值的类型 * @param {Tag} tag - 上下文标签 * @param {object} ctx - 要设置的上下文对象 * @param {() => R} fn - 要在上下文中运行的函数 * @returns {R} 函数的执行结果 * * @description * 1. 在执行函数前设置指定的上下文 * 2. 函数执行完成后自动恢复之前的上下文状态 * 3. 如果函数返回Promise,则会在Promise完成后自动删除该上下文 * 4. 无论函数执行成功或失败,都会确保上下文状态被正确恢复 */ static run(tag, ctx, fn) { const restore = this.set(tag, ctx, true); try { const result = fn(); // 如果是异步函数,则等待其执行完成后删除上下文 if (isPromise(result)) { result.finally(() => this.unset(tag, ctx)); } return result; } finally { restore(); } } /** * 在异步任务中管理上下文 * * @async * @template T - 异步任务的返回值类型 * @param {AsyncContextTask<T>} asyncTask - 需要执行的异步任务 * @param {Tag[]} [tags=[]] - 需要挂起的上下文标签数组,不传入则会挂起所有上下文 * @returns {Promise<T>} 异步任务的执行结果 * @throws {Error} 如果异步任务执行失败 * * @description * 1. 执行异步任务前会临时挂起指定的上下文(或所有上下文) * 2. 任务完成后会自动恢复原来的上下文状态 * 3. 如果tags参数为空数组,则会挂起所有上下文 * 4. asyncTask可以是返回Promise的函数或直接传入的Promise对象 * 5. 无论任务成功或失败,都会确保上下文状态被正确恢复 */ static async withAsyncContext(asyncTask, tags = []) { // 如果 asyncTask 是一个函数,则调用它以获取 Promise if (isFunction(asyncTask)) { asyncTask = asyncTask(); } // 如果 asyncTask 不是 Promise,则直接返回 if (!isPromise(asyncTask)) return asyncTask; let restoreContext; // 如果指定了需要挂起的上下文标签 if (isArray(tags) && tags.length > 0) { const backup = new Map(); // 备份并删除指定的上下文 tags.forEach(tag => { const context = this.get(tag); if (context !== undefined) { backup.set(tag, context); __classPrivateFieldGet(this, _a, "f", _Context_store).delete(tag); } }); // 定义恢复上下文的函数 restoreContext = () => { backup.forEach((value, key) => value && __classPrivateFieldGet(this, _a, "f", _Context_store).set(key, value)); backup.clear(); }; } else { // 如果未指定标签,则挂起所有上下文 const prevStore = __classPrivateFieldGet(this, _a, "f", _Context_store); __classPrivateFieldSet(this, _a, new Map(), "f", _Context_store); restoreContext = () => (__classPrivateFieldSet(this, _a, prevStore, "f", _Context_store)); } try { // 执行异步任务并返回结果 return await asyncTask; } finally { // 无论任务成功与否,恢复上下文 restoreContext(); } } /** * 清除所有上下文 * * @warning 谨慎使用!此操作会清除所有上下文状态 */ static clear() { __classPrivateFieldGet(this, _a, "f", _Context_store).clear(); } /** * 设置指定标签的上下文 * * @template T - 上下文对象的类型 * @param {Tag} tag - 上下文标签 * @param {T} ctx - 要设置的上下文对象 * @param {boolean} [backup=true] - 是否备份当前上下文 * @returns {RestoreContext} 用于恢复上下文的函数 * * @description * 1. 如果backup为true,会备份当前上下文,并在调用返回的恢复函数时恢复 * 2. 如果backup为false,调用恢复函数时会直接删除该上下文 * 3. 返回的恢复函数可以多次调用,但只有第一次调用会生效 */ static set(tag, ctx, backup = true) { const prev = backup ? __classPrivateFieldGet(this, _a, "f", _Context_store).get(tag) : undefined; __classPrivateFieldGet(this, _a, "f", _Context_store).set(tag, ctx); return () => { // 前一个上下文存在,则恢复前一个上下文,否则删除当前上下文 if (prev) { __classPrivateFieldGet(this, _a, "f", _Context_store).set(tag, prev); return true; } else { return this.unset(tag, ctx); } }; } } _a = Context; // 上下文存储商店 _Context_store = { value: new Map() };