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);
    }
}

 

posted on 2023-01-10 10:32  疯狂的妞妞  阅读(816)  评论(0编辑  收藏  举报

导航