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 ...
随机推荐
- 风险识别系统-大数据智能风控管理平台-企业风控解决方案– 阿里云 https://www.aliyun.com/product/saf
风险识别系统-大数据智能风控管理平台-企业风控解决方案– 阿里云 https://www.aliyun.com/product/saf
- https://tools.ietf.org/html/rfc8017
PKCS #1: RSA Cryptography Specifications Version 2.2
- You shouldn't use *any* general-purpose hash function for user passwords, not BLAKE2, and not MD5, SHA-1, SHA-256, or SHA-3
hashlib - Secure hashes and message digests - Python 3.8.3 documentation https://docs.python.org/3.8 ...
- Python的交互模式和直接运行.py文件有什么区别
使用文本编辑器 - 廖雪峰的官方网站 https://www.liaoxuefeng.com/wiki/1016959663602400/1017024645952992 直接输入python进入交互 ...
- css选择器有哪些,选择器的权重的优先级
选择器类型 1.ID #id 2.class .class 3.标签 p 4.通用 * 5.属性 [type="text"] 6.伪类 :hover 7.伪元素 ::first-l ...
- JasperReports 取消自动分页/忽略分页
因为需要将合同比价单由PDF文档形式改为HTML页面方式,虽然转换文档类型了,但是发现HTML页面中间到了一定行数就出现了空行把Detail给隔开了.之前总想着怎样消除中间空行,以为是报表top页面边 ...
- Struts 2学习(二)
文章目录 @[toc] #动态结果 配置时不知道执行后的结果是哪一个,运行时才知道哪个结果作为视图显示给用户. #全局结果 全局就结果可满足一个包中多个Action共享一个结果. 全局结果位于pack ...
- GeoMesa Spark
GeoMesa Spark 一.Spark JTS 1.1 示例 1.2配置 1.3 地理空间用户定义的类型和功能 1.4 geojson输出 1.5 Building 二.Spark Core 2. ...
- php之在admin的目录下的php文件里加上JSON的报头,运行php文件会提示下载
去掉报头就正常,但在前端引用数据时要加上JSON.parse,不然读不出数据. $.get("fetchUpLast.php",{ rd:new Date().getTime()} ...
- 分布式-springboot基础入门
B站播放地址:https://www.bilibili.com/video/BV1PE411i7CV?t=51 博客地址:https://www.cnblogs.com/hellokuangshen/ ...