First of all, let’s understand the shallow principle of setTimeout. SetTimeout is executed through the browser asynchronous API. After the execution is completed, the callback is handed over to the macro task.

The browser executes 60 frames in 1s, and the execution time difference between the two frames is about 16ms, which is considered a better experience.

RequestAnimationFrame does not require a set time, and is executed in about 16ms. So using requestAnimationFrame is more accurate

<! SetInterval --> export function mySetInterval(cb, cancelCb) {let timer = null; let pre = new Date() let fn = function() { timer = requestAnimationFrame(() => { let cur = new Date() if (cur - pre >= 1000) { cb() pre = cur } timer = requestAnimationFrame(fn) if (cancelCb && cancelCb()) { timer && cancelAnimationFrame(timer) } }) } fn() } <! --> export default class Countdown {constructor({endTime}) {this.endtimetamp = new Date(endTime).getTime() console.log(endTime, this.endTimetamp); this.countDownDate = {} mySetInterval(this.countDown.bind(this), this.cancel.bind(this)) } countDown() { let dis = (this.endTimetamp - new Date().getTime()) / 1000 this.countDownDate = This.calculator (dis) console.log(' send event ---->', this.countdowndate); // this.on('countdown', this.countDownDate) } cancel() { return this.countDownDate && this.countDownDate.timetamp <= 0 ? true : false } calculator(second) { let sec = 1, min = 60 * sec, hour = 60 * min, day = 24 * hour; return { day: parseInt(second / day), hour: parseInt(second % day / hour), min: parseInt(second % hour / min), second: parseInt(second % min), timetamp: second } } } export default Countdown new Countdown({ endTime: '2021-11-30 12:00' })Copy the code

Advantages:

  1. Perform on time
  2. Decouple with component logic