• setInterval&setTimeout的暂停和继续


    /*
        author: leeenx
        @ timer 对象
        @ 提供 7 个API如下:
        @ timer.setTimeout(fun, delay[, id])
        @ timer.clearTimeout(id)
        @ timer.setInterval(fun, delay[, id])
        @ timer.clearInterval(id)
        @ timer.delete(id) 删除对应id的timeout/interval
        @ timer.pause(id) 暂停对应id的timeout/interval
        @ timer.resume(id) 恢复对应id的timeout/interval
        @ timer.clean() 清空所有 timeout & interval
    */
    
    class Timer {
        // 构造函数 
        constructor() {
            // 暂停状态 - 这是个公共状态,由外部 Ticker 决定。
            this.paused = true;
    
            // 队列
            this.queue = new Map();
    
            // 正在使用 timer 的 RAF
            this.usingRAF = false;
    
            // useRAF 触发器
            Reflect.defineProperty(this, "useRAF", {
                set: function (value) {
                    Reflect.set(this, "usingRAF", value);
                    value ? Timer.RAF.enable() : Timer.RAF.disable();
                }
            });
        }
    
        // setTimeout 的实现
        setTimeout(fn, delay, id = Symbol("timeoutID")) {
            // 存入队列 
            this.queue.set(id, {
                fn: fn,
                type: 0,
                paused: 0,
                elapsed: 0,
                delay: delay
            });
            return id;
        }
    
        // clearTimeout
        clearTimeout(id) {
            return this.delete(id);
        }
    
        // setInterval 的实现
        setInterval(fn, delay, id = Symbol("intervalID")) {
            // 存入队列
            this.queue.set(id, {
                fn: fn,
                type: 1,
                paused: 0,
                elapsed: 0,
                delay: delay
            });
            return id;
        }
    
        // clearInterval
        clearInterval(id) {
            return this.delete(id);
        }
    
        // 修改指定id的 delay/fn
        set(id, config = {}) {
            let item = this.queue.get(id) || {};
            for (let key in config) {
                item[key] = config[key];
            }
            return true;
        }
    
        // 删除 queue 上的成员
        delete(id) {
            return this.queue.delete(id);
        }
    
        // 暂停指定id
        pause(id) {
            id === undefined ? this.pauseAll() : (this.queue.get(id).paused = 1);
            return true;
        }
    
        // 恢复指定id
        resume(id) {
            return this.play(id);
        }
    
        // 播放指定id
        play(id) {
            id === undefined ? this.playAll() : (this.queue.get(id).paused = 0);
            return true;
        }
    
        // 清空timer
        clean() {
            this.queue = new Map();
            return true;
        }
    
        // 暂停全部 id
        pauseAll() {
            this.queue.forEach((item) => item.paused = 1);
            return true;
        }
    
        // 播放全部 id
        playAll() {
            this.queue.forEach((item) => item.paused = 0);
            return true;
        }
    
        // 重置 elapsed 为 0
        reset = function (id) {
            id === undefined ? this.resetAll() : (this.queue.get(id).elapsed = 0);
        }
    
        // 重置所有的 elapsed 为 0
        resetAll = function () {
            this.queue.forEach(function (item) { item.elapsed = 0 });
        }
    
        // tick
        tick(delta) {
            this.paused || this.updateQueue(delta);
        }
    
        // 更新 map 队列
        updateQueue(delta) {
            this.queue.forEach((item, id) => {
                if (item.paused === 1) return;
                item.elapsed += delta;
                if (item.elapsed >= item.delay) {
                    item.fn();
                    item.type === 0 ? this.delete(id) : (item.elapsed = 0);
                }
            });
        }
    
        // 状态更新
        update() {
            // 第一次调用 update 时主动停用原生接口
            this.useRAF = false;
    
            // 下面是真正的 update
            this.update = (delta) => {
                if (this.usingRAF) return;
                this.tick(delta);
            }
        }
    
    }
    
    class AnimationFrame {
        constructor() {
            this.time = 0;
            this.auto = this.auto.bind(this);
        }
        auto(elapsed) {
            timer.tick(elapsed - this.time);
            this.time = elapsed;
            this.id = requestAnimationFrame(this.auto);
        }
        enable() {
            timer.paused = false;
            this.id = requestAnimationFrame(this.auto);
        }
        disable() {
            cancelAnimationFrame(this.id);
        }
    }
    
    // 原生RAF
    Timer.RAF = new AnimationFrame();
    
    // 对外接口
    let timer = new Timer();
    
    // 默认使用原生 RAF
    timer.useRAF = true;
    // 导出timer
    export default timer;
    

      原文:JELLY | 实现 setTimeout & setInterval 暂停 (jd.com)

  • 相关阅读:
    【移动端】300ms延迟以及点透事件原因以及解决方案
    javaScript drag对象进行拖拽使用详解
    js文件上传原理(form表单 ,FormData + XHR2 + FileReader + canvas)
    Linux常用bash命令
    一些好的关于网络知识的博客
    python 2 处理HTTP 请求的包
    python 3 处理HTTP 请求的包
    接口测试笔记
    接口测试资料
    PyH : python生成html
  • 原文地址:https://www.cnblogs.com/ckAng/p/14524103.html
Copyright © 2020-2023  润新知