js——带暂停、启动功能的定时
简单的封装,将 interval 二次封装,对外提供暂停、启动功能。
不足之处:interval定时间隔是固定的,在调用异步函数的时候,可能会出现bug。
例如:定时发送ajax请求,定时间隔1秒,发送a、b两个请求,a请求需要5秒,而b只需要1秒。b是后发送的,但是先获取到执行结果,这时候逻辑上可能会产生问题。
(这种情况,需要用setTimeout()封装,等待前一个ajax完全结束,再启动下一个。业务代码与定时任代码会发生强耦合,暂时不考虑封装)
let Scheduled = function () { } /** * 循环作业 * * @param call 任务 * @param timeout 时间间隔 * @return {{isRunning: (function(): boolean), start: (function(): void), parse: (function(): void)}} * @constructor */ let CycleWork = function (call, timeout) { let interval = undefined; return { /** * 暂停 * * @returns void */ parse: function () { if (interval !== undefined) { window.clearInterval(interval); interval = undefined; } }, /** * 启动任务 * * @returns void */ start: function () { interval = window.setInterval(call, timeout); }, /** * 是否在跑批中 * * @return {boolean} */ isRunning: function () { return interval !== undefined; } } } /** * 循环作业,按照特定区间执行的循环作业,这在循环读取数据的业务中非常实用 * * @param call 任务 * @param timeout 时间间隔 * @returns {{restart: restart, isRunning: (function(): boolean), start: start, range: range, parse: parse}} * @constructor */ let RangeCycleWork = function (call, timeout) { let range = [0, 0]; let idx = 0; let work = new CycleWork(() => { if (idx < range[1]) { call(idx); idx++; } if (idx >= range[1]) { work.parse(); } }, timeout); return { /** * 区间 * @param r{[]} 区间 */ range: function (r) { range = r; idx = r[0]; }, /** * 暂停 * * @returns void */ parse: function () { work.parse(); }, /** * 启动任务 * * @returns void */ start: function () { work.start(); }, /** * 启动任务,指针回到开始位置,从头开始循环 * * @returns void */ restart: function () { idx = range[0]; work.start(); }, /** * 是否在跑批中 * * @return {boolean} */ isRunning: function () { work.isRunning(); } } } /** * 具有倒计时功能的循环作业,达到次数之后,结束任务 * * @param call{Function} 任务 * @param times{number} 循环次数次数 * @param timeout{number} 时间间隔 * @return {number} Interval ID */ Scheduled.prototype.countdownWork = function (call, times, timeout) { let n = Math.abs(times); let interval = window.setInterval(() => { if (n === 0) { window.clearInterval(interval); } else { n--; call(n); } }, timeout); } /** * * 循环作业,达到次数之后,结束任务 * * @param call{Function} 任务 * @param times{number} 循环次数次数 * @param timeout{number} 时间间隔 * @return {number} Interval ID */ Scheduled.prototype.startCycleWork = function (call, times, timeout) { let idx = 0, n = Math.abs(times); let interval = window.setInterval(() => { if (idx < n) { window.clearInterval(interval); } else { call(idx); idx++; } }, timeout); return interval; } /** * 循环作业 * @param call 任务 * @param timeout 时间间隔 * @return {{isRunning: (function(): boolean), start: (function(): void), parse: (function(): void)}} * @constructor */ Scheduled.prototype.CycleWork = CycleWork; /** * 循环作业 * @param call 任务 * @param timeout 时间间隔 * @return {{isRunning: (function(): boolean), start: (function(): void), parse: (function(): void)}} * @constructor */ Scheduled.prototype.RangeCycleWork = RangeCycleWork; //保证单例,不需要第二个Scheduled let scheduled = new Scheduled(); export default scheduled;
使用方式:
import Scheduled from '../../components/widget/scheduled' export default { created: function () { let work = new Scheduled.CycleWork(()=>{console.log('test')}, 1000); work.start(); Scheduled.runCycleWork(()=>{console.log('test2')}, 3, 1000); } }
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!