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 ...
随机推荐
- c++hook内联汇编模板
1 #include "Windows.h" 2 #include "tlhelp32.h" 3 #include "String.h" 4 ...
- SSL_ERROR_WANT_READ
``` 47757 2020/05/07 06:36:04 [debug] 19413#19413: *23421 event timer: 11, old: 15581551413, new: 15 ...
- 【C++小知识】#define、enum、const的含义与用法
一.#define 含义 define是宏定义,编译器不对其进行错误检查,在预编译阶段处理,没有作用域限制属于全局常量,在程序中编译器会对定义的常量名以数值进行替换,且每次替换都分配内存,此方法对于大 ...
- Excel 常用数据类型、自定义格式、特殊值等等
常用数据类型: 常规: 常规单元榴格式不包含慑拍H靛的数字格式. 数值: 可以设置小数位数,是否使用千位分割符,以及负数样式 货币: 可以设置小数位数,货币符号,以及负数样式 会计专用: 可以设置小数 ...
- Prometheus—告警altermanger
Prometheus-告警altermanger 1.告警altermanger装配 2.告警Mysql 3.Prometheus针对nodes告警规则配置 相关内容原文地址链接: 51CTO:wfw ...
- 设计模式c++(3)——观察者模式
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖着都会收到通知并自动更新. 当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节.观察者模式提供了一种对象设 ...
- Java中的transient关键字,使用小结
transient关键字的介绍: 一个对象只要实现了Serilizable接口,这个对象就可以被序列化,Java的这种序列化模式为开发者提供了很多便利,可以不必关系具体序列化的过程,只要这个类实现了S ...
- indexedDB数据库的使用
<!DOCTYPE html> <html> <head> <title>indexedDB数据库的使用</title> <meta ...
- @AliasFor 注解
Spring 框架提供了很丰富的注解可以让我们很方便的进行 Spring 配置,今天要讲的注解--@AliasFor之前你可能并没有关注过,因为平时开发时我们的确不太会用到. 我关注到这个注解是因为我 ...
- POJ-3208 Apocalypse Someday (数位DP)
只要某数字的十进制表示中有三个6相邻,则该数字为魔鬼数,求第X小的魔鬼数\(X\le 5e7\) 这一类题目可以先用DP进行预处理,再基于拼凑思想,用"试填法"求出最终的答案 \( ...