(function (global) { 'use strict'; var DEFAULT_BUDGET_MS = 2; /** * 空闲切片调度:单次回调预算默认 2ms,可跨帧续跑。 * @param {function(function():boolean):void} work 入参 isExpired(),返回 false 表示还有剩余工作 * @param {number=} budgetMs */ function runIdle(work, budgetMs) { var budget = budgetMs > 0 ? budgetMs : DEFAULT_BUDGET_MS; var schedule = function (fn) { if (typeof global.requestIdleCallback === 'function') { global.requestIdleCallback(fn, { timeout: 200 }); } else { global.setTimeout(fn, 0); } }; var step = function () { var start = performance.now(); var expired = function () { return performance.now() - start >= budget; }; var more = true; try { work(expired); // work 约定:若需续跑,在内部检测 expired 后自行再次 schedule;此处兼容返回值 } catch (e) { console.warn('[调试工作台] idle 任务失败', e); more = false; } return more; }; // 简化:提供 runChunks 辅助 schedule(function () { step(); }); } /** * 分片遍历数组。 * @param {Array} list * @param {function(*,number):void} visit * @param {function():void=} onDone * @param {number=} budgetMs */ function forEachChunk(list, visit, onDone, budgetMs) { var i = 0; var budget = budgetMs > 0 ? budgetMs : DEFAULT_BUDGET_MS; var tick = function () { var start = performance.now(); while (i < list.length && performance.now() - start < budget) { visit(list[i], i); i += 1; } if (i < list.length) { if (typeof global.requestIdleCallback === 'function') { global.requestIdleCallback(tick, { timeout: 200 }); } else { global.setTimeout(tick, 0); } } else if (onDone) { onDone(); } }; tick(); } global.PWIdle = { budgetMs: DEFAULT_BUDGET_MS, run: runIdle, forEachChunk: forEachChunk, }; })(window);