export type ListenerCallback = (currentTime: number, overTime: number) => boolean; export interface Listen { currentTime: number; overTime: number; callback: ListenerCallback; } export interface Scheduler { /** 向事件池插入事件的数组 */ listens: Listen[]; /** 锁枕 */ frameLock: boolean; } /** 更新循环, 在整个应用生命周期中每帧检测是否需要更新界面 */ function updateLoop(data: Scheduler): void { if (!data) { return; } const listensLength = data.listens.length; const listens = data.listens; data.frameLock = false; if (listensLength) { const time = Date.now(); listens.forEach((listen) => { // 判断listen是否存在,有可能callback里会执行removeListener,然后listen被销毁了 if (listen) { // execTimestamp为0代表还没初始化 if (listen.currentTime === 0) { listen.currentTime = time; } listen.overTime = time - listen.currentTime; // callback返回ture表示函数已正确执行,将重置execTimestamp if (listen.callback(time, listen.overTime)) { listen.currentTime = time; } } }); } } /** * 向更新循环添加回调 * @param _source 框架内部使用 */ function addListener(getData: () => Scheduler, callback: ListenerCallback): void { const data = getData(); if (data) { data.listens.push({ callback, currentTime: 0, overTime: 0, }); } else { setTimeout(() => { addListener(getData, callback); }, 300); } } /** 向更新循环删除回调 */ function removeListener(data: Scheduler, callback: ListenerCallback): void { const listens = data.listens; const index = listens.findIndex((item: Listen) => item.callback === callback); if (index >= 0) { listens.splice(index, 1); } } /** 每帧执行 */ function frame(getData: () => Scheduler, callback: (time: number, overTime: number) => void) { const data = getData(); const listener = (time: number, overTime: number) => { if (data.frameLock === false) { callback(time, overTime); data.frameLock = true; } return false; }; addListener(getData, listener); return listener; } /** * 同window.setTimeout * @param cb 请传递函数的引用,clearlTimeOut需要函数引用 * @param delay 延迟时间 */ function setTimeOut(getData: () => Scheduler, callback: () => void, delay: number): ListenerCallback { const data = getData(); const listenerCallback: ListenerCallback = (currentTime: number, overTime: number): boolean => { if (overTime >= delay) { callback(); removeListener(data, listenerCallback); return true; } return false; }; addListener(getData, listenerCallback); return listenerCallback; } /** * 同window.clearTimeout * @param callback 传递给setTimeOut的函数引用 */ function clear(data: Scheduler, callback?: ListenerCallback | null) { if (callback) { removeListener(data, callback); } } function setInterval(getData: () => Scheduler, callback: () => void, delay: number) { const listenerCallback: ListenerCallback = (currentTime: number, overTime: number): boolean => { if (overTime >= delay) { callback(); return true; } return false; }; addListener(getData, listenerCallback); return listenerCallback; } /** * 函数防抖 */ function debounce>(getData: () => Scheduler, callback: (...args: T) => void, delay: number) { let listener: ListenerCallback | undefined; let initTime: number | undefined; const create = (...args: T) => { initTime = undefined; listener = setTimeOut(getData, () => { callback(...args); }, delay); }; return (...args: T) => { const time = Date.now(); if (initTime === undefined) { initTime = time; } if (time - initTime < delay) { clear(getData(), listener); create(...args); // } }; } /** 暂停代码执行一段时间 */ function wait(value: number) { return new Promise((reslove) => { setTimeout(() => { reslove(true); }, value); }); } export { updateLoop, addListener, removeListener, frame, setTimeOut, clear, debounce, wait, setInterval };