|
|
|
|
(function (global) {
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
var DEFAULT_BUDGET_MS = 2;
|
|
|
|
|
|
|
|
|
|
function scheduleIdle(fn) {
|
|
|
|
|
if (typeof global.requestIdleCallback === 'function') {
|
|
|
|
|
global.requestIdleCallback(fn, { timeout: 200 });
|
|
|
|
|
} else {
|
|
|
|
|
global.setTimeout(fn, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 空闲切片调度:单次回调预算默认 2ms,可跨帧续跑。
|
|
|
|
|
* @param {function(function():boolean):boolean|void} work
|
|
|
|
|
* 入参 isExpired();返回 false 表示还有剩余工作,应继续调度。
|
|
|
|
|
* @param {number=} budgetMs
|
|
|
|
|
*/
|
|
|
|
|
function runIdle(work, budgetMs) {
|
|
|
|
|
var budget = budgetMs > 0 ? budgetMs : DEFAULT_BUDGET_MS;
|
|
|
|
|
var step = function () {
|
|
|
|
|
var start = performance.now();
|
|
|
|
|
var expired = function () {
|
|
|
|
|
return performance.now() - start >= budget;
|
|
|
|
|
};
|
|
|
|
|
var more = true;
|
|
|
|
|
try {
|
|
|
|
|
more = work(expired) !== false;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[调试工作台] idle 任务失败', e);
|
|
|
|
|
more = false;
|
|
|
|
|
}
|
|
|
|
|
if (more === false) scheduleIdle(step);
|
|
|
|
|
};
|
|
|
|
|
scheduleIdle(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) {
|
|
|
|
|
scheduleIdle(tick);
|
|
|
|
|
} else if (onDone) {
|
|
|
|
|
onDone();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
tick();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
global.PWIdle = {
|
|
|
|
|
budgetMs: DEFAULT_BUDGET_MS,
|
|
|
|
|
run: runIdle,
|
|
|
|
|
forEachChunk: forEachChunk,
|
|
|
|
|
schedule: scheduleIdle,
|
|
|
|
|
};
|
|
|
|
|
})(window);
|