UNPKG

@antv/x6

Version:

JavaScript diagramming library that uses SVG and HTML for rendering

167 lines 5.65 kB
const SCHEDULE_MODE = { idle: 'idle', raf: 'raf', timeout: 'timeout', }; export class JobQueue { constructor() { this.isFlushing = false; this.isFlushPending = false; this.scheduleId = 0; this.queue = []; this.frameInterval = 16; this.initialTime = Date.now(); this.pendingJobs = new Map(); this.scheduleMode = null; } queueJob(job) { if (job.priority & JOB_PRIORITY.PRIOR) { job.cb(); } else { const existing = this.pendingJobs.get(job.id); if (existing) { // 仅更新已有任务的回调与优先级 existing.cb = job.cb; if (job.priority !== existing.priority) { existing.priority = job.priority; const idx = this.queue.indexOf(existing); if (idx >= 0) { this.queue.splice(idx, 1); const newIndex = this.findInsertionIndex(existing); this.queue.splice(newIndex, 0, existing); } } } else { const index = this.findInsertionIndex(job); this.queue.splice(index, 0, job); this.pendingJobs.set(job.id, job); } } } queueFlush() { if (!this.isFlushing && !this.isFlushPending) { this.isFlushPending = true; this.scheduleJob(); } } queueFlushSync() { if (!this.isFlushing && !this.isFlushPending) { this.isFlushPending = true; this.flushJobsSync(); } } clearJobs() { this.queue.length = 0; this.pendingJobs.clear(); this.isFlushing = false; this.isFlushPending = false; this.cancelScheduleJob(); } flushJobs(deadline) { this.isFlushPending = false; this.isFlushing = true; const startTime = this.getCurrentTime(); let budget = this.frameInterval; if (deadline && typeof deadline.timeRemaining === 'function') { const remain = deadline.timeRemaining(); // 防止过长占用单帧 budget = Math.max(0, Math.min(budget, remain)); } while (this.queue.length > 0) { const job = this.queue.shift(); job.cb(); this.pendingJobs.delete(job.id); if (this.getCurrentTime() - startTime >= budget) { break; } } this.isFlushing = false; if (this.queue.length) { this.queueFlush(); } } flushJobsSync() { this.isFlushPending = false; this.isFlushing = true; while (this.queue.length > 0) { const job = this.queue.shift(); try { job.cb(); } catch (error) { console.error(error); } this.pendingJobs.delete(job.id); } this.isFlushing = false; } findInsertionIndex(job) { let left = 0; let ins = this.queue.length; let right = ins - 1; const priority = job.priority; while (left <= right) { const mid = ((right - left) >> 1) + left; if (priority <= this.queue[mid].priority) { left = mid + 1; } else { ins = mid; right = mid - 1; } } return ins; } scheduleJob() { if (this.scheduleId) { this.cancelScheduleJob(); } if ('requestAnimationFrame' in window) { this.scheduleMode = SCHEDULE_MODE.raf; this.scheduleId = window.requestAnimationFrame(() => this.flushJobs()); } else if ('requestIdleCallback' in window) { this.scheduleMode = SCHEDULE_MODE.idle; this.scheduleId = window.requestIdleCallback((deadline) => this.flushJobs(deadline), { timeout: 100, }); } else { this.scheduleMode = SCHEDULE_MODE.timeout; this.scheduleId = window.setTimeout(() => this.flushJobs()); } } cancelScheduleJob() { if (!this.scheduleId) return; const cancelMethods = { [SCHEDULE_MODE.idle]: window === null || window === void 0 ? void 0 : window.cancelIdleCallback, [SCHEDULE_MODE.raf]: window === null || window === void 0 ? void 0 : window.cancelAnimationFrame, [SCHEDULE_MODE.timeout]: window === null || window === void 0 ? void 0 : window.clearTimeout, }; const mode = this.scheduleMode; const cancelMethod = mode ? cancelMethods[mode] : undefined; if (typeof cancelMethod === 'function') { cancelMethod(this.scheduleId); } this.scheduleId = 0; this.scheduleMode = null; } getCurrentTime() { const hasPerformanceNow = typeof performance === 'object' && typeof performance.now === 'function'; if (hasPerformanceNow) { return performance.now(); } return Date.now() - this.initialTime; } } export var JOB_PRIORITY; (function (JOB_PRIORITY) { JOB_PRIORITY[JOB_PRIORITY["Update"] = 2] = "Update"; JOB_PRIORITY[JOB_PRIORITY["RenderEdge"] = 4] = "RenderEdge"; JOB_PRIORITY[JOB_PRIORITY["RenderNode"] = 8] = "RenderNode"; JOB_PRIORITY[JOB_PRIORITY["PRIOR"] = 1048576] = "PRIOR"; })(JOB_PRIORITY || (JOB_PRIORITY = {})); //# sourceMappingURL=queueJob.js.map