当前位置: 首页 > news >正文

学校网站建设规划书排名sem优化软件

学校网站建设规划书,排名sem优化软件,国家高新技术企业有哪些,室内设计培训班靠谱吗今天想要分享的是一个面试题,也是一个我们在项目中常用的功能:倒计时。 首先我们在写倒计时的时候必须要考虑到是:准确性、性能。接下来我们一步一步实现这个完美地倒计时功能。 setInterval 先来简单实现一个倒计时的函数: func…

今天想要分享的是一个面试题,也是一个我们在项目中常用的功能:倒计时。

首先我们在写倒计时的时候必须要考虑到是:准确性性能。接下来我们一步一步实现这个完美地倒计时功能。

  • setInterval

    先来简单实现一个倒计时的函数:

    function example1(leftTime) {let t = leftTime;setInterval(() => {t = t - 1000;console.log(t);}, 1000);
    }example1(10);
    

    可以看到使用 setInterval 即可,但是setInterval 真的准确吗?我们来看一下 MDN 中的说明:

    如果你的代码逻辑执行时间可能比定时器时间间隔要长,建议你使用递归调用了 setTimeout() 的具名函数

    例如,使用 setInterval() 以 5 秒的间隔轮询服务器,可能因网络延迟、服务器无响应以及许多其他的问题而导致请求无法在分配的时间内完成。

    简单来说意思就是,js 因为是单线程的原因,如果前面有阻塞线程的任务,那么就可能会导致 setInterval 函数延迟,这样倒计时就肯定会不准确,建议使用 setTimeout 替换 setInterval

  • setTimeout

    按照上述的建议将 setInterval 换为 setTimeout 后,我们来看下代码:

    function example2(leftTime) {let t = leftTime;setTimeout(() => {t = t - 1000;if (t > 0) {console.log(t);example2(t);}console.log(t);}, 1000);
    }
    

    MDN 中也说了,有很多因素会导致 setTimeout 的回调函数执行比设定的预期值更久,比如嵌套超时、非活动标签超时、追踪型脚本的节流、超时延迟等等。 总之呢就是和 setInterval 差不多,时间一长,就会有误差出现,而且setTimeout有一个很不好的点在于,当你的程序在后台运行时,setTimeout也会一直执行,这样会严重的而浪费性能,那么有什么办法可以解决这种问题吗?

  • requestAnimationFrame

    这里就不得不提一个新的方法 requestAnimationFrame,它是一个浏览器 API,允许以 60 帧/秒 (FPS) 的速率请求回调,而不会阻塞主线程。通过调用 requestAnimationFrame 方法浏览器会在下一次重绘之前执行指定的函数,这样可以确保回调在每一帧之间都能够得到适时的更新。 这个 API 我们在大屏可视化项目中需要动态切换图表数据时也是常用的。

    那么我们使用 requestAnimationFrame 结合 setTimeout 来优化一下之前的代码:

    function example4(leftTime) {let t = leftTime;function start() {requestAnimationFrame(() => {t = t - 1000;setTimeout(() => {console.log(t);start();}, 1000);});}start();
    }
    
    为什么要使用 requestAnimationFrame + setTimeout呢?

    原因一个是息屏或者切后台的操作时,requestAnimationFrame 是不会继续调用函数的,但是如果只使用requestAnimationFrame 的话,函数相当于 1 秒的时候要调用 60 次,太浪费性能。

    在切后台或者息屏的实际操作执行时会发现,当回到页面时,倒计时会接着切后台时的时间执行,而没有更新到最新的时间,这样的bug是接受不了的。

  • diffTime差值计算

    要解决上述的问题,最通用的办法就是通过时间差值每次进行对比就可以了。

    function example5(leftTime) {const now = performance.now();function start() {setTimeout(() => {const diff = leftTime - (performance.now() - now);console.log(diff);requestAnimationFrame(start);}, 1000);}start();
    }
    

    上面的代码实现思路其实在实际的业务中已经能够满足我们的使用场景,但其实还是没有解决setTimeout会延迟的问题,当线程被占用之后,很容易出现误差,那么有什么更新的办法进行处理呢?

最佳方案

先要明确的是,setTimeout函数中执行代码的时间肯定是要大于等于setTimeout时间的,那么就可能出现设定的 1 秒,实际执行却执行了 2 秒的情况,那么我们的实现思路也很简单,每次计算一下setTimeout实际执行的时间,然后动态的调整下一次执行的时间,而不是设置固定的值。

我们来用图表举例推演一下每次执行的情况:

第n次执行executionTime 实际执行时间nextTime 下次需要执行的时间totleTime 执行的总时间
0010000
112008001200
211007002300
310007003300
422005005500
513002006800
6120010008000

从中可以看到:下次执行的时间 nextTime = 1000 - totleTime % 1000;这样我们就可以得出下次执行的时间,从而每次都去动态的调整多余消耗的时间,大大减小倒计时最终的误差

还有需要考虑的是,实际业务中返回的剩余时间肯定不会是整数,所以我们的第一次执行的时间最好可以先让剩余时间变为整数,这样可以在倒计时到最后一秒时更加的精确。

根据上述的思路来看一下最终封装出来的 react hooks:

const useCountDown = ({ leftTime, ms = 1000, onEnd }) => {const countdownTimer = useRef();const startTimer = useRef();//记录初始时间const startTimeRef = useRef(performance.now());// 第一次执行的时间处理,让下一次倒计时时调整为整数const nextTimeRef = useRef(leftTime % ms);const [count, setCount] = useState(leftTime);const clearTimer = () => {countdownTimer.current && clearTimeout(countdownTimer.current);startTimer.current && clearTimeout(startTimer.current);};const startCountDown = () => {clearTimer();const currentTime = performance.now();// 算出每次实际执行的时间const executionTime = currentTime - startTimeRef.current;// 实际执行时间大于上一次需要执行的时间,说明执行时间多了,否则需要补上差的时间const diffTime =executionTime > nextTimeRef.current? executionTime - nextTimeRef.current: nextTimeRef.current - executionTime;setCount((count) => {const nextCount =count - (Math.floor(executionTime / ms) || 1) * ms - nt;return nextCount <= 0 ? 0 : nextCount;});// 算出下一次的时间nextTimeRef.current =executionTime > nextTimeRef.current ? ms - diffTime : ms + diffTime;// 重置初始时间startTimeRef.current = performance.now();countdownTimer.current = setTimeout(() => {requestAnimationFrame(startCountDown);}, nextTimeRef.current);};useEffect(() => {setCount(leftTime);startTimer.current = setTimeout(startCountDown, nextTimeRef.current);return () => {clearTimer();};}, [leftTime]);useEffect(() => {if (count <= 0) {clearTimer();onEnd && onEnd();}}, [count]);return count;
};export default useCountDown;

如果想要封装组件的话,可以在hooks的基础上进行二次封装。

到这里,肯定会有人说,做了这么多的操作,有必要吗,就算差0点几秒,在实际体验中用户完全感受不出来。我想说的是,细节决定成败,有可能这零点几秒的内容就决定了面试的成败。如果做什么事都只做个差不多,那你永远不会有自己的"核心科技"。

http://www.khdw.cn/news/24285.html

相关文章:

  • 做网络平台的网站有哪些抖音广告投放平台官网
  • 宁波网站建设公司地址关键词优化seo外包
  • 郑州网站建设最便宜营销网站推荐
  • 企业网站的网址通常包括百度seo优化技术
  • wordpress文章存储天津谷歌优化
  • 做任务能赚钱的网站有哪些武汉seo公司哪家好
  • 网站制作公司汉狮网络网站seo关键词设置
  • 网站炫酷首页青岛网站建设公司电话
  • 四川建设银行手机银行下载官方网站我想找一个营销团队
  • 河南郑州做网站汉狮seo网站优化培训找哪些
  • 宁波网站推广seo服务价格表
  • 南昌企业制作网站网站测速
  • 嘉定装饰装修网站域名大全免费网站
  • 谷歌seo算法规则seo能干一辈子吗
  • 用树莓派做网站服务器关键词排名优化怎么样
  • 台州建站模板搭建长沙专业网站制作
  • 宁河网站建设怎么创建网站的快捷方式
  • 高端网站建设公司哪里济南兴田德润实惠吗sem模型
  • 用模板做网站教程网站百度收录查询
  • 网站移动端适配怎么做整站优化seo平台
  • 芜湖做网站推广有哪些公司客户资源买卖平台
  • 网站建设一条龙服务免费b站推广入口
  • 做视频比较好的理财网站有哪些seo业务培训
  • 武汉网站建设公司027推广软件平台
  • 邯郸做网站优化沙坪坝区优化关键词软件
  • 做国外网站用什么颜色成都网站快速优化排名
  • 长沙好的网站建设公司排名移动优化课主讲:夫唯老师
  • 网站建设规划书电商免费推广的方式有哪些
  • 简约好看的网站百度推广的费用
  • 毕业论文代做网站是真的吗企业网络营销策略分析