在订单数据提交后,一般会规定在一定的时间内支付,这时就需要一个倒计时来提醒用户
下面的代码 依赖 dayjs 模块
// 要先引入 dayjs 模块
import dayjs from "@/utils/dayjs/dayjs.min.js";
// 接收 处理好的时间 例:15:00
let payment_time = "";
// 保存定时器 以便在不需要的时候清除掉
let paymentCountDown_time = null;
// 在外部定义一个结束时间
let expire_time = dayjs("2023-02-25 15:00");
// 支付倒计时
function paymentCountDown() {
// 开始时间
const startTime = dayjs();
// 结束时间
const expireTime = dayjs(expire_time);
// 获取相差的时间 seconds:秒
const mins = expireTime.diff(startTime, "seconds", true);
// 获取分钟
const totalHours = parseInt(mins / 60);
// 获取秒
const totalMins = dayjs().minute(mins).$m;
// 不足10在前面补0
const makeUpZero = num => (num < 10 ? `0${num}` : num);
payment_time = `${makeUpZero(totalHours)}:${makeUpZero(totalMins)}`;
// 当分钟或者秒大于0时 定时器循环调用
if (totalHours > 0 || totalMins > 0) {
paymentCountDown_time = setTimeout(() => {
paymentCountDown();
}, 1000);
} else {
// 倒计时结束,清除掉定时器
clearTimeout(paymentCountDown_time);
paymentCountDown_time = null;
}
};
// 在需要的位置调用一次函数
paymentCountDown();
// 在不需要的时候清除掉定时器
clearTimeout(paymentCountDown_time);
paymentCountDown_time = null;
js中setTimeout定时器不准的原因,以及修正的办法
因为 setTimeout 是一个异步任务,在执行到 setTimeout 的时候,js 引擎不会立刻把定时任务放到事件循环的任务队列中,而是等待时间到了,再放进事件循环的队列中。
setTimeout 定时器不准,意味着,设置的定时任务 1s 后执行,但由于 setTimeout 是异步任务 ,导致可能晚于 1s 后才执行。注意,不会提前于 1s 执行。
注意,是时间到了才加入队列,那么如果队列中已经有了其他的任务要执行,这个新加的定时器任务自然要等待前面的任务结束,所以时间会延后。
我们只能尽量调整延后的时间偏差,不能修正到完全精确
// 要先引入 dayjs 模块
import dayjs from "@/utils/dayjs/dayjs.min.js";
// 接收 处理好的时间 例:15:00
let payment_time = "";
// 保存定时器 以便在不需要的时候清除掉
let paymentCountDown_time = null;
// 在外部定义一个结束时间
let expire_time = dayjs("2023-02-25 15:00");
// 记录定时器执行开始前的时间戳 performance.now 比 Date.now 更精确
let start_time = performance.now();
// time_count 表示定时器被调用的次数,次数需要是全局变量
let time_count = 0;
// 支付倒计时
function paymentCountDown() {
// 记录函数开始执行时的时间
const runTime = performance.now();
console.log("runTime: ", runTime);
// 先增加定时器的次数
++time_count;
// diffTime 就是已经延后的时间
const diffTime = runTime - (start_time + time_count * 1000);
console.log("diffTime: ", diffTime, time_count);
// 开始时间
const startTime = dayjs();
// 结束时间
const expireTime = dayjs(expire_time);
// 获取相差的时间 seconds:秒
const mins = expireTime.diff(startTime, "seconds", true);
// 获取分钟
const totalHours = parseInt(mins / 60);
// 获取秒
const totalMins = dayjs().minute(mins).$m;
// 不足10在前面补0
const makeUpZero = num => (num < 10 ? `0${num}` : num);
payment_time = `${makeUpZero(totalHours)}:${makeUpZero(totalMins)}`;
// 当分钟或者秒大于0时 定时器循环调用
if (totalHours > 0 || totalMins > 0) {
paymentCountDown_time = setTimeout(() => {
paymentCountDown();
}, 1000);
} else {
// 倒计时结束,清除掉定时器
clearTimeout(paymentCountDown_time);
paymentCountDown_time = null;
}
};
// 在需要的位置调用一次函数
paymentCountDown();
// 在不需要的时候清除掉定时器
clearTimeout(paymentCountDown_time);
paymentCountDown_time = null;
可以在页面中定义个耗时任务来测试 setTimeout 定时器
//耗时任务
setInterval(function(){
var i = 0;
while(i++ < 100000000);
}, 0);
uniapp + uview组件库的 < u-count-down></ u-count-down>
<template>
<u-count-down @change="resetChange" :time="time" format="mm:ss" autoStart millisecond></u-count-down>
</template>
<script>
export default {
data() {
return {
time: 0,
};
},
created() {
this.time = this.getTimeDate();
console.log('this.time: ', this.time);
},
methods: {
// 获取倒计时
getTimeDate() {
if (!'2023-11-27 10:00:00') return 0; // 如果订单的创建时间不存在,返回0
const createTime = new Date('2023-11-27 10:00:00').getTime(); // 将订单创建时间转换为毫秒数
const now = new Date().getTime(); // 获取当前时间的毫秒数
// 1000 * 60 * 5 的毫秒数
const timeLimit = 1000 * 60 * 5; // 设置倒计时时间限制为 5 分钟的毫秒数
// 结束时间
const endTime = createTime + timeLimit;
const diff = endTime - now; // 计算结束时间与当前时间的时间差
return endTime <= now ? 0 : diff; // 如果 结束时间 大于等于 当前时间,则返回0,否则返回时间差
},
}
}
</script>