How to implement an accurate countdown timer with js

How to implement an accurate countdown timer with js

如何用 js 实现一个精确的倒计时器

How to implement an accurate countdown timer with js_第1张图片

原理剖析

  1. web worker

  2. js custom timer

  3. 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);
}


How to implement an accurate countdown timer with js_第2张图片

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();



  1. 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

How to implement an accurate countdown timer with js_第3张图片

refs


Flag Counter

©xgqfrms 2012-2020

www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!


你可能感兴趣的:(How to implement an accurate countdown timer with js)