Vue 移动端活动倒计时优化

前言

通常写倒计时效果,用的是 setInterval,但这会引发一些问题,最常见的问题就是定时器不准。

如果只是普通的动画效果,倒也无所谓,但倒计时这种需要精确到毫秒级别的,就不行了,否则活动都结束了,用户的界面上倒计时还在走,但是又参加不了活动,会被投诉的╮(╯▽╰)╭

一、 知识铺垫

1. setInterval 定时器

先说本文的主角 setInterval,MDN web doc 对其的解释是:

setInterval() 方法重复调用一个函数或执行一个代码段,在每次调用之间具有固定的时间延迟。

返回一个 intervalID。(可用于清除定时器)

语法: let intervalID = window.setInterval(func, delay[, param1, param2, ...]);
例:

值得注意的是,在 setInterval 里面使用 this 的话,this 指向的是 window 对象,可以通过 call、apply 等方法改变 this 指向。

setTimeout 与 setInterval 类似,只不过延迟 n 毫秒执行函数一次,且不需要手动清除。

至于 setTimeout 和 setInterval 的运行原理,就要牵扯到另一个概念: event loop (事件循环)。

2. 浏览器的 Event Loop

JavaScript 在执行的过程中会产生执行环境,这些执行环境会被顺序的加入到执行栈中,若遇到异步的代码,会被挂起并加入到 task (有多种 task) 队列中。

一旦执行栈为空, event loop 就会从 task 队列中拿出需要执行的代码并放入执行栈中执行。

有了 event loop,使得 JavaScript 具备了异步编程的能力。(但本质上,还是同步行为)

先看一道经典的面试题:

console.log('Script start');setTimeout(() => {console.log('setTimeout');
}, 0);new Promise((resolve, reject) => {console.log('Promise');resolve()
}).then(() => {console.log('Promise 1');
}).then(() => {console.log('Promise 2');
});console.log('Scritp end'); 

打印顺序为:

  1. “Script start”
  2. “Promise”
  3. “Script end”
  4. “Promise 1”
  5. “Promise 2”
  6. “setTimeout”

至于为什么 setTimeout 设置为 0,却在最后被打印,这就涉及到 event loop 中的微任务和宏任务了。

2.1 宏任务和微任务

不同的任务源会被分配到不同的 task 队列中,任务源可分为微任务( microtask )和宏任务( macrotask ).

在 ES6 中:

  • microtask 称为 Job
  • macrotask 称为 Task

macro-task(Task): 一个 event loop 有一个或者多个 task 队列。task 任务源非常宽泛,比如 ajax 的 onload,click 事件,基本上我们经常绑定的各种事件都是 task 任务源,还有数据库操作(IndexedDB ),需要注意的


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部