原生JS实现简单计时器

本文最后更新于:8 个月前

在线预览: 点我查看demo

做什么

用原生的js实现一个简单计时器。比如说记录编辑框他输入内容所用的时间。

怎么做

HTML

一个编辑框和一个时间显示器

JS

编辑框获得焦点时setInterval()进行计时,失去焦点时clearInterval()取消计时
另外利用localStorage可以进行数据的保存,刷新后能读取上次的时间

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计时器</title>
</head>
<body>
<div id="container">
<h3 id="status">计时器案例 - 未做题</h3>
<textarea rows="5" cols="20" onfocus="inputFocus()" onblur="innputBlur()" placeholder="点击输入框开始计时"></textarea>
<h4 id="timer">做题时长: 0时0分0秒</h4>
<button onclick="resetTime()">重新计时</button>
</div>

<script>
var second = 0; //记录时间-秒
var timing; //定时器

//更新显示时间
function updateTime(){
let _hour = Math.floor(second /3600);
let _minute = Math.floor((second%3600) / 60);
let _second = (second%3600) %60;
document.getElementById("timer").innerText = "做题时长:"+_hour+"时"+_minute+"分"+_second+"秒";
}

function resetTime(){
window.localStorage.setItem("status",0);
second = 0;
updateTime();
}
//输入框获得焦点时开始计时
function inputFocus(){
document.getElementById("status").innerText = "计时器案例 - 做题中";
timing = setInterval(function(){
second ++;
updateTime();
},1000);
}

//输入框失去焦点取消计时
function innputBlur(){
document.getElementById("status").innerText = "计时器案例 - 未做题";
clearInterval(timing);
}

//网页加载完执行数据初始化
window.onload = function(){
let t = window.localStorage.getItem("time");
second = t?t:0; //无数据时默认为0
updateTime();
}

//网页刷新前进行数据缓存
window.onbeforeunload = function(){
innputBlur();
window.localStorage.setItem("time",second);
}
</script>
</body>
</html>

思考

是否可以利用两个开始和结束的两个时间戳获取一个时间段?但是需要注意的是我们new Date()获取的时间可能会受到系统时间的影响,导致获取的数据不合法。(2020-06-06)

setTimeoutsetInterval究竟谁更适合实现计时?

看了红宝书,里面说了一句setInterval很少会出现在生产环境。于是想到了该计时器的实现。

setInterval到了时间就会把回调函数推进消息队列,所以不适合长时间和阻塞的循环任务,比如时间长的ajax不断被推进消息队列,然后消息队列越来越长,影响整个系统。与此同时,不能保证两次任务之间保持间隔。setTimeout实现循环任务就能保证任务有间隔,上一次任务成功回调才到下一次。

然而对于计时器这种比较简单的任务来说,不至于出现setInterval被塞爆的情况。而且计时器我们关注的是到时间就把回调推进消息队列,而不是两次时间增长之间保持间隔。

所以我认为在这个场景下,setInterval是更适合计时器的。(2020-11-18)

另外,由于JS的运行机制。两种定时器的实现方式都是有微小误差的。而performance中的计时api适合于性能检测等高精度时间计算,不适合用在这


原生JS实现简单计时器
https://www.chanx.tech/2020/c3c099a07c97/
作者
ischanx
发布于
2020年6月6日
更新于
2023年8月7日
许可协议