How to implement an accurate countdown timer with js
How to implement an accurate countdown timer with js
如何用 js 实现一个精确的倒计时器

原理剖析
web worker
js custom timer
setTimeout / setInterval async bug (宏任务)
"use strict";
/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @created 2020-07-0
* @modified
*
* @description 使用 JavaScript 实现精确的 setTimeout 和 setInterval
* @difficulty Easy Medium Hard
* @complexity O(n)
* @augments
* @example
* @link
* @solutions
*
*/
const log = console.log;
// 同步: 使用 js 实现精确的 setTimeout
function setTimeoutPreciseSimulator(callback, time = 0) {
const begin = new Date().getTime();
while (true) {
const end = new Date().getTime();
if(end - begin >= time) {
log(`end - begin`, end - begin);
callback();
break;
}
}
}
// 同步: 使用 js 实现精确的 setInterval
function setIntervalPreciseSimulator(callback, time = 0, count = 10) {
function interval(callback, time) {
const begin = new Date().getTime();
while (true) {
const end = new Date().getTime();
if(end - begin >= time) {
log(`end - begin`, end - begin);
callback();
break;
}
}
if(count) {
log(`\ncount =`, count);
count--;
interval(callback, time);
}
}
// init
interval(callback, time);
}

solution
"use strict";
/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @created 2020-07-24
* @modified
*
* @description 如何用 js 实现一个精确的倒计时器
* @difficulty Easy Medium Hard
* @complexity O(n)
* @augments
* @example
* @link https://gaohaoyang.github.io/2016/11/25/how-to-write-a-count-down/
* @solutions
*
*/
const log = console.log;
// 同步: 使用 js 实现精确的 setTimeout
function setTimeoutPreciseSimulator(callback, time = 0) {
const begin = new Date().getTime();
while (true) {
const end = new Date().getTime();
if(end - begin >= time) {
// log(`end - begin`, end - begin);
callback();
break;
}
}
}
// 同步: 使用 js 实现精确的 setInterval
function setIntervalPreciseSimulator(callback, time = 0) {
function interval(callback, time) {
const begin = new Date().getTime();
while (true) {
const end = new Date().getTime();
if(end - begin >= time) {
// log(`end - begin`, end - begin);
callback();
break;
}
}
if(!hasFished) {
interval(callback, time);
}
}
// init
interval(callback, time);
}
// 首次进入页面获取 server 的时间和 server 剩余的时间 / server 结束的时间
const autoCalculatorRemainTime = (serverTime, endTime) => {
// const now = Date.parse(new Date());
// const now = new Date().getTime();
let total = endTime - serverTime;// ms
while(total) {
const seconds = Math.floor((total / 1000) % 60);
const minutes = Math.floor((total / (1000 * 60)) % 60);
const hours = Math.floor((total / (1000 * 60 * 60)) % 24);
const days = Math.floor(total / (1000 * 60 * 60 * 24));
total -= 1000;
setTimeoutPreciseSimulator(() => {
log(`days hours minutes seconds =\n`, `${days}天-${hours}时-${minutes}分-${seconds}秒`);
}, 1000);
// log(`days hours minutes seconds =\n`, `${days}天-${hours}时-${minutes}分-${seconds}秒`);
}
log(` 倒计时结束!`);
// return {
// total,
// days,
// hours,
// minutes,
// seconds,
// };
}
// DOM demo
new Date(`2020-07-30 11:00:00`).getTime();
// 1596078000000
new Date(`2020-07-30 11:00:01`).getTime();
// 1596078001000
// 3分钟后, 1s === 1000ms, 3 * 60 * 1000 === 180000ms
new Date(`2020-07-30 11:00:00`).getTime() + 3 * 60 * 1000;
// 1596078180000
const serverTime = new Date().getTime();
// 3分钟后
const endTime = new Date(serverTime + 3 * 60 * 1000).getTime();
autoCalculatorRemainTime(serverTime, endTime);
// let hasFished = false;
// setIntervalPreciseSimulator();
- new Date() 获取时间差,计算
/**
* 获取剩余时间
* @param {Number} endTime 截止时间
* @param {Number} deviceTime 设备时间
* @param {Number} serverTime 服务端时间
* @return {Object} 剩余时间对象
*/
const getRemainTime = (endTime, deviceTime, serverTime) => {
let t = endTime - Date.parse(new Date()) - serverTime + deviceTime;
let seconds = Math.floor((t / 1000) % 60);
let minutes = Math.floor((t / 1000 / 60) % 60);
let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
let days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds,
};
}
demo
https://www.online-stopwatch.com/chinese/
https://www.online-stopwatch.com/chinese/full-screen-stopwatch.php

refs
xgqfrms 2012-2020
www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
How to implement an accurate countdown timer with js的更多相关文章
- jQuery Countdown Timer 倒计时效果
这个一款简单的 jQuery 倒计时插件,用于显示剩余的天数,小时,分钟和秒.倒计时功能是非常有用的一个小功能,可以告诉用户多久以后您的网站将会发布或者关闭进行维护,还可以用于举办活动的开始和停止的倒 ...
- A WPF/MVVM Countdown Timer
Introduction This article describes the construction of a countdown timer application written in C# ...
- 深入出不来nodejs源码-timer模块(JS篇)
鸽了好久,最近沉迷游戏,继续写点什么吧,也不知道有没有人看. 其实这个node的源码也不知道该怎么写了,很多模块涉及的东西比较深,JS和C++两头看,中间被工作耽搁回来就一脸懵逼了,所以还是挑一些简单 ...
- Implement Custom Cache Dependencies in ASP.NET 1.x
Code download available at:CuttingEdge0407.exe(128 KB) Contents What's a Cache Dependency, Anyway? ...
- Java中定时器相关实现的介绍与对比之:Timer和TimerTask
Timer和TimerTask JDK自带,具体的定时任务由TimerTask指定,定时任务的执行调度由Timer设定.Timer和TimerTask均在包java.util里实现. 本文基于java ...
- System and method for controlling switching between VMM and VM using enabling value of VMM timer indicator and VMM timer value having a specified time
In one embodiment, a method includes transitioning control to a virtual machine (VM) from a virtual ...
- JUC回顾之-ScheduledThreadPoolExecutor底层实现原理和应用
项目中经常使用定时器,比如每隔一段时间清理下线过期的F码,或者应用timer定期查询MQ在数据库的配置,根据不同version实现配置的实时更新等等.但是timer是存在一些缺陷的,因为Timer在执 ...
- Adaptively handling remote atomic execution based upon contention prediction
In one embodiment, a method includes receiving an instruction for decoding in a processor core and d ...
- Adaptive partitioning scheduler for multiprocessing system
A symmetric multiprocessing system includes multiple processing units and corresponding instances of ...
随机推荐
- Spark底层原理详细解析(深度好文,建议收藏)
Spark简介 Apache Spark是用于大规模数据处理的统一分析引擎,基于内存计算,提高了在大数据环境下数据处理的实时性,同时保证了高容错性和高可伸缩性,允许用户将Spark部署在大量硬件之上, ...
- 获取控制台的错误信息 onerror
js 获取控制台的错误信息 https://www.bbsmax.com/A/Vx5ML2NmJN/ <!DOCTYPE html> <html lang="en" ...
- innodb和myisam原理
MyISAM索引实现 MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址.如图: 这里设表一共有三列,假设我们以Col1为主键,则上图是一个MyISAM表的主索引 ...
- Apache Hudi 0.7.0版本重磅发布
重点特性 1. Clustering 0.7.0版本中支持了对Hudi表数据进行Clustering(对数据按照数据特征进行聚簇,以便优化文件大小和数据布局),Clustering提供了更灵活地方式增 ...
- 404 GET /nbextensions/jupyter-js-widgets/extension.js
数据科学交流群,群号:189158789,欢迎各位对数据科学感兴趣的小伙伴的加入! 解决办法: 首先要确定你安装和配置nbextensions时有没有加--user,如果当时没加这里就不用加,否则不一 ...
- (3)UNIX/Linux系统结构
UNIX/Linux 系统可以粗糙地抽象为 3 个层次,如图所示.底层是 UNIX/Linux 操作系统,即系统内核(Kernel):中间层是Shell层,即命令解释层:高层则是应用层. 1) 内核层 ...
- 零基础如何使用python处理字符串?
摘要:Python的普遍使用场景是自动化测试.爬取网页数据.科学分析之类,这其中都涉及到了对数据的处理,而数据的表现形式很多,今天我们来讲讲字符串的操作. 字符串是作为任意一门编程语言的基础,在P ...
- 解决 error MSB4057: 该项目中不存在目标“_CopyWebApplication” 问题
在使用MSBuild 编译项目的时候报错: 解决办法: 在Web项目中,使用Nuget添加引用 MSBuild.Microsoft.VisualStudio.Web.targets 即可.
- 2019牛客暑期多校训练营(第十场)E-Hilbert Sort(分形)
>传送门< 题意 现给出你 $n $个坐标和 $k$,让你根据$ k$阶 希尔伯特曲线的走向排列给出的 $n $个坐标 希尔伯特曲线如下: $k=1$ $k=2$ $k=3$可以将边长为 ...
- AcWing 250 磁力快(分块)
题目传送门 在一片广袤无垠的原野上,散落着N块磁石. 每个磁石的性质可以用一个五元组(x,y,m,p,r)描述,其中x,y表示其坐标,m是磁石的质量,p是磁力,r是吸引半径. 若磁石A与磁石B的距离不 ...