performance.now 实现准确的倒计时
perfromance.now是什么? performance.now 是一个函数,它返回以毫秒为单位的时间值(double类型)。返回的值表示自执行开始以来经过的时间。
解决什么问题? 使用new Date()方式实现的倒计时会受到系统时间的影响,比如修改系统时间,就可以修改倒计时的时间。 在JavaScript中,perfromance.now()方法可用于检查代码的性能。您可以使用此方法检查代码的执行时间。
用法:
Javascript
let t = performance.now();
下面的代码将使您对该代码的执行方式有一个简短的了解。
Javascript
<script>
const t0 = performance.now();
for (let i = 0; i < 10; i++) {
console.log(i);
}
const t1 = performance.now();
console.log(`Call to doSomething took ${t1 - t0} milliseconds.`);
</script>
- 根据这个特性,我们可以使用performance.now 实现不受系统时间影响的倒计时
- Demo
倒计时1-服务器时间
倒计时2-毫秒数倒计时
<template>
<div>
<div>
<div
style="
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
"
>
<div class="title">倒计时1-服务器时间</div>
<div class="currentTime"></div>
<div>
<n-button class="stopBtn">stop</n-button>
<n-button class="pauseBtn">pause</n-button>
</div>
</div>
<br />
<div
style="
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
"
>
<div class="title">倒计时2-毫秒数倒计时</div>
<div class="currentTime2"></div>
<div>
<n-button class="stopBtn2">stop</n-button>
<n-button class="pauseBtn2">pause</n-button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted } from "vue";
onMounted(async () => {
var localStartTime;
var ServeTime = await getServerTime();
var ServeEndTime = await getServerEndTime();
// 服务器当前时间
function getCurrentServeTime() {
return ServeTime + (performance.now() - localStartTime);
}
// 服务器剩余时间数
async function getTime() {
return ServeEndTime - getCurrentServeTime();
}
// 毫秒转天时分秒
function formatDuring(mss) {
var days = parseInt(mss / (1000 * 60 * 60 * 24));
var hours = parseInt((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = parseInt((mss % (1000 * 60 * 60)) / (1000 * 60));
var seconds = (mss % (1000 * 60)) / 1000;
return (
days +
" 天 " +
hours +
" 小时 " +
minutes +
" 分钟 " +
seconds.toFixed() +
" 秒 "
);
}
async function getServerTime() {
localStartTime = performance.now();
return Promise.resolve(new Date("2023-06-02 12:00:00").getTime());
}
async function getServerEndTime() {
return Promise.resolve(new Date("2023-06-02 12:01:00").getTime());
}
/**
* @description: 开启定时器
* @param {*} time // 毫秒数
* @param {*} callback 没帧的回调,返回剩余毫秒数
* @return {*} { stop,pause } 返回停止和暂停函数
*/
function setTime(time, callback) {
// 开启标志符
var isProgressing = false;
// 本地结束时间
let localEndTime = performance.now() + time;
function next() {
// 剩余的毫秒数
let residueTime = localEndTime - performance.now();
residueTime = residueTime > 0 ? residueTime : 0;
if (typeof callback == "function") {
callback(residueTime);
}
if (residueTime > 0 && !isProgressing) {
requestAnimationFrame(next);
}
}
// 停止
function stop() {
isProgressing = true;
localEndTime = 0;
// callback(0) // 停止是否清零
}
// 暂停/开始
function pause() {
isProgressing = !isProgressing;
if (isProgressing === false && localEndTime != 0) {
// 重新开始重置本地结束时间
localEndTime = performance.now() + time;
next();
} else {
// 获得剩余的时间
time = localEndTime - performance.now();
}
}
next();
return {
stop,
pause,
};
}
async function start1() {
var time = await getTime();
let { stop, pause } = setTime(time, (residueTime) => {
let currentText = formatDuring(residueTime);
let dom = document.querySelector(".currentTime");
dom.innerHTML = currentText;
});
let btn = document.querySelector(".stopBtn");
btn.addEventListener("click", stop);
let btn2 = document.querySelector(".pauseBtn");
btn2.addEventListener("click", pause);
}
async function start2() {
var time = await getTime();
let { stop, pause } = setTime(60000, (residueTime) => {
let currentText = formatDuring(residueTime > 0 ? residueTime : 0);
let dom = document.querySelector(".currentTime2");
dom.innerHTML = currentText;
});
let btn = document.querySelector(".stopBtn2");
btn.addEventListener("click", stop);
let btn2 = document.querySelector(".pauseBtn2");
btn2.addEventListener("click", pause);
}
start1();
start2();
});
</script>
<style lang="scss" scoped></style>