Promise then 中实现钩子函数
思路:
在 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')
}
})