徐向博 / Imin.

Promise then 中实现钩子函数
作者:Imin 时间:2023-03-15 分类: 前端

思路:

在 promise 的 then 方法中,给一个 action 参数,在action 上可以挂在各种需要的钩子函数。


知识点

js事件循环中的宏任务和微任务


举个栗子,需求如下:

创建一个方法,为dom对象创建倒计时,并需要在倒计时开始、过程中、结束时做出响应。


代码如下:

HTMLElement.prototype.countDown = function (endTime, run = true){
    return new Promise(callback => {
        // 处理参数
        let dom = this;
        let time = new Date(endTime);
        const endString = '00天00时00分00秒';

        // 初始化钩子函数
        const action = {
            start (){},
            progress (){},
            end (){}
        }
        
        // 日期格式错误
        if(time == 'Invalid Date'){
            console.warn(`${endTime}不是一个合法的日期字符串。`);
            return false;
        }

        // 数字补0
        const to2 = num => num < 10 ? '0' + num : num;

        // 秒差,转换成字符串
        let end = time.getTime()/1000;
        const outTime = () => {
            let start = parseInt(new Date().getTime()/1000);
            let variance = end - start;
            let day = parseInt(variance / 86400);
            let hour = parseInt((variance - day * 86400) / 3600);
            let minute = parseInt((variance - day * 86400 - hour * 3600) / 60);
            let second = variance - day * 86400 - hour * 3600 - minute * 60;
            if(day > 0 || hour > 0 || minute > 0 || second > 0){
                return `${to2(day)}天${to2(hour)}时${to2(minute)}分${to2(second)}秒`;
            }else{
                return endString;
            }
        }

        // 倒计时已过期
        if(outTime() == endString){
            dom.innerHTML = endString;
            return;
        }

        // 倒计时未过期,输出
        if(run){
            let interval = setInterval(() => {
                let tempTime = outTime();
                dom.innerHTML = tempTime;
                action.progress(tempTime);
                if(tempTime == endString){
                    clearInterval(interval);
                    action.end();
                }
            }, 1000);
        }else{
            dom.innerHTML = outTime();
        }

        // 倒计时开始时执行
        let timeout = setTimeout(() => {
            clearTimeout(timeout);
            action.start();
        }, 0)

        callback(action);
    })
}


调用如下:

document.querySelector('.countDown').countDown('2023/03/15 00:43:50').then(action => {
    action.start = function(){
        console.log('start')
    }
    action.progress = function (time){
        console.log(time) // 参数time代表当前进度
    }
    action.end = function(){
        console.log('end')
    }
})


本文标签: 钩子函数 promise