/*** Synchronous state machine for the query lifecycle, compatible with* React's `useSyncExternalStore`.** Three states:* idle → no query, safe to dequeue and process* dispatching → an item was dequeued, async chain hasn't reached onQuery yet* running → onQuery called tryStart(), query is executing** Transitions:* idle → dispatching (reserve)* dispatching → running (tryStart)* idle → running (tryStart, for direct user submissions)* running → idle (end / forceEnd)* dispatching → idle (cancelReservation, when processQueueIfReady fails)** `isActive` returns true for both dispatching and running, preventing* re-entry from the queue processor during the async gap.** Usage with React:* const queryGuard = useRef(new QueryGuard()).current* const isQueryActive = useSyncExternalStore(* queryGuard.subscribe,* queryGuard.getSnapshot,* )*/import { createSignal } from './signal.js'export class QueryGuard {private _status: 'idle' | 'dispatching' | 'running' = 'idle'private _generation = 0private _changed = createSignal()/*** Reserve the guard for queue processing. Transitions idle → dispatching.* Returns false if not idle (another query or dispatch in progress).*/reserve(): boolean {if (this._status !== 'idle') return falsethis._status = 'dispatching'this._notify()return true}/*** Cancel a reservation when processQueueIfReady had nothing to process.* Transitions dispatching → idle.*/cancelReservation(): void {if (this._status !== 'dispatching') returnthis._status = 'idle'this._notify()}/*** Start a query. Returns the generation number on success,* or null if a query is already running (concurrent guard).* Accepts transitions from both idle (direct user submit)* and dispatching (queue processor path).*/tryStart(): number | null {if (this._status === 'running') return nullthis._status = 'running'++this._generationthis._notify()return this._generation}/*** End a query. Returns true if this generation is still current* (meaning the caller should perform cleanup). Returns false if a* newer query has started (stale finally block from a cancelled query).*/end(generation: number): boolean {if (this._generation !== generation) return falseif (this._status !== 'running') return falsethis._status = 'idle'this._notify()return true}/*** Force-end the current query regardless of generation.* Used by onCancel where any running query should be terminated.* Increments generation so stale finally blocks from the cancelled* query's promise rejection will see a mismatch and skip cleanup.*/forceEnd(): void {if (this._status === 'idle') returnthis._status = 'idle'++this._generationthis._notify()}/*** Is the guard active (dispatching or running)?* Always synchronous — not subject to React state batching delays.*/get isActive(): boolean {return this._status !== 'idle'}get generation(): number {return this._generation}// --// useSyncExternalStore interface/** Subscribe to state changes. Stable reference — safe as useEffect dep. */subscribe = this._changed.subscribe/** Snapshot for useSyncExternalStore. Returns `isActive`. */getSnapshot = (): boolean => {return this._status !== 'idle'}private _notify(): void {this._changed.emit()}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。