沐游虞笔记
  • 前端面试题

    • HTML面试题汇总(无答案)
    • HTML面试题汇总
    • CSS 面试题汇总(无答案)
    • CSS 面试题汇总
    • javascript 面试题汇总(无答案)
    • javascript 面试题汇总
    • promise 面试题(无答案)
    • promise 面试题
    • 浏览器面试题汇总(无答案)
    • 浏览器面试题汇总
    • 网络面试题汇总(无答案)
    • 网络面试题汇总
    • 工程化面试题汇总(无答案)
    • 工程化面试题汇总
    • VUE面试题汇总(无答案)
    • VUE面试题汇总
  • 直播课文件

    • 静态页面学习指导
    • 属性的计算过程
    • 层叠继承规则总结
    • BFC
    • JS基础知识回顾
    • DOM 事件的传播机制
    • DOM 事件的注册和移除
    • 阻止事件默认行为
    • 基础领航考试题
    • 基础领航考试题(答案)
    • 2024前端发展
    • JS核心概念学习指导
    • 第三方库与工程化学习指导
    • Vue入门学习指导
    • vue进阶学习指导
    • 前端性能优化
  • 笔面试环节知识讲解

    • 目录
    • 图像处理
    • 图像处理(面试)
    • Webpack构建优化
    • Webpack构建优化(面试)
    • TTS性能优化
    • TTS性能优化(面试)
    • 实时协作
    • 实时协作(面试)
    • 网页复制图片到剪贴板
    • 网页复制图片到剪贴板(面试)
    • vite插件
    • vite插件(面试)
    • 表单数据同步与保持
    • 表单数据同步与保持(面试)
    • 优化虚拟列表
    • 优化虚拟列表(面试)
    • 微前端解决巨石应用
    • 微前端解决巨石应用(面试)
    • DNS解析与优化
    • DNS解析与优化(面试)
    • 前端监控
    • 前端监控(面试)
    • 12.跨标签页通信
    • 12.跨标签页通信(面试)
    • 13.Vite相关优化
    • 13.Vite相关优化(面试)
    • 14.计时器节流问题
    • 14.计时器节流问题(面试)
    • 15.多文件预览支持
    • 15.多文件预览支持(面试)
    • 16.defer优化白屏时间
    • 16.defer优化白屏时间(面试)
  • Vue3整体变化
  • Vue2响应式回顾
  • Vue3响应式变化
  • nextTick实现原理
  • 两道代码题
  • Vue运行机制
  • 渲染器核心功能
  • 事件绑定与更新
  • computed面试题
  • watch面试题
  • 图解双端diff
  • 图解快速dff
  • 最长递增子序列
  • 模板编译器
  • 模板编译提升
  • 组件name作用
  • 路由传参方式
  • 基础篇

    • 序章React介绍
    • JSX基础语法
    • React基本介绍
    • 表单
    • 生命周期
    • 组件与事件绑定
    • 组件状态与数据传递
    • Hooks
    • React--redux介绍
    • React-router介绍
  • 就业篇

    • 属性默认值和类型验证
    • 高阶组件
    • Ref
    • Context
    • Render Props
    • Portals
    • 错误边界
    • 组件渲染性能优化
    • 前端框架的理解
    • Reacti和Vue描述页面的区别
    • 前端框架的分类
    • 虚拟DoM
    • React整体架构
    • React渲染流程
    • Fiber双缓冲
    • MessageChannel
    • Scheduleri调度普通任务
    • Scheduleri调度延时任务
    • 最小堆
    • React中的位运算
    • beginWork工作流程
    • completeWork工作流程
    • 图解diff算法
    • commit工作流程
    • lane模型
    • React中的事件
    • Hooks原理
    • useStateuseReducer.
    • effect相关hook
    • useCallbackuseMemo
    • useRef
    • Update
    • 性能优化策略之eagerState
    • 性能优化策略之bailout
    • bailoutContextAPl
    • 性能优化对日常开发启示
  • 前端监控概述
  • 错误监控
  • 数据上报
  • 页面性能监控
  • 用户行为收集与埋点
  • CSS3手册
  • HTML5手册
  • JavaScript语言提升

    • es补充
    • 事件循环
    • promise基础
    • Promise的链式调用
    • Promise的静态方法
    • async和await
    • Promise相关面试题
  • 网络

    • 客户端与服务器
    • 关于 Apifox 的使用
  • git文档
  • 工程化

    • CommonJS
    • ES module
    • npm文档(包管理)
    • Lass笔记
    • webpack工具
  • canvas详解
  • uinapp笔记
  • 自动化测试
  • oauth2令牌

    • 认识Oauth2
    • 三方应用实现github授权
    • 微信三方应用登录实现
    • 支付宝沙箱支付功能
  • 前端面试题

    • HTML面试题汇总(无答案)
    • HTML面试题汇总
    • CSS 面试题汇总(无答案)
    • CSS 面试题汇总
    • javascript 面试题汇总(无答案)
    • javascript 面试题汇总
    • promise 面试题(无答案)
    • promise 面试题
    • 浏览器面试题汇总(无答案)
    • 浏览器面试题汇总
    • 网络面试题汇总(无答案)
    • 网络面试题汇总
    • 工程化面试题汇总(无答案)
    • 工程化面试题汇总
    • VUE面试题汇总(无答案)
    • VUE面试题汇总
  • 直播课文件

    • 静态页面学习指导
    • 属性的计算过程
    • 层叠继承规则总结
    • BFC
    • JS基础知识回顾
    • DOM 事件的传播机制
    • DOM 事件的注册和移除
    • 阻止事件默认行为
    • 基础领航考试题
    • 基础领航考试题(答案)
    • 2024前端发展
    • JS核心概念学习指导
    • 第三方库与工程化学习指导
    • Vue入门学习指导
    • vue进阶学习指导
    • 前端性能优化
  • 笔面试环节知识讲解

    • 目录
    • 图像处理
    • 图像处理(面试)
    • Webpack构建优化
    • Webpack构建优化(面试)
    • TTS性能优化
    • TTS性能优化(面试)
    • 实时协作
    • 实时协作(面试)
    • 网页复制图片到剪贴板
    • 网页复制图片到剪贴板(面试)
    • vite插件
    • vite插件(面试)
    • 表单数据同步与保持
    • 表单数据同步与保持(面试)
    • 优化虚拟列表
    • 优化虚拟列表(面试)
    • 微前端解决巨石应用
    • 微前端解决巨石应用(面试)
    • DNS解析与优化
    • DNS解析与优化(面试)
    • 前端监控
    • 前端监控(面试)
    • 12.跨标签页通信
    • 12.跨标签页通信(面试)
    • 13.Vite相关优化
    • 13.Vite相关优化(面试)
    • 14.计时器节流问题
    • 14.计时器节流问题(面试)
    • 15.多文件预览支持
    • 15.多文件预览支持(面试)
    • 16.defer优化白屏时间
    • 16.defer优化白屏时间(面试)
  • Vue3整体变化
  • Vue2响应式回顾
  • Vue3响应式变化
  • nextTick实现原理
  • 两道代码题
  • Vue运行机制
  • 渲染器核心功能
  • 事件绑定与更新
  • computed面试题
  • watch面试题
  • 图解双端diff
  • 图解快速dff
  • 最长递增子序列
  • 模板编译器
  • 模板编译提升
  • 组件name作用
  • 路由传参方式
  • 基础篇

    • 序章React介绍
    • JSX基础语法
    • React基本介绍
    • 表单
    • 生命周期
    • 组件与事件绑定
    • 组件状态与数据传递
    • Hooks
    • React--redux介绍
    • React-router介绍
  • 就业篇

    • 属性默认值和类型验证
    • 高阶组件
    • Ref
    • Context
    • Render Props
    • Portals
    • 错误边界
    • 组件渲染性能优化
    • 前端框架的理解
    • Reacti和Vue描述页面的区别
    • 前端框架的分类
    • 虚拟DoM
    • React整体架构
    • React渲染流程
    • Fiber双缓冲
    • MessageChannel
    • Scheduleri调度普通任务
    • Scheduleri调度延时任务
    • 最小堆
    • React中的位运算
    • beginWork工作流程
    • completeWork工作流程
    • 图解diff算法
    • commit工作流程
    • lane模型
    • React中的事件
    • Hooks原理
    • useStateuseReducer.
    • effect相关hook
    • useCallbackuseMemo
    • useRef
    • Update
    • 性能优化策略之eagerState
    • 性能优化策略之bailout
    • bailoutContextAPl
    • 性能优化对日常开发启示
  • 前端监控概述
  • 错误监控
  • 数据上报
  • 页面性能监控
  • 用户行为收集与埋点
  • CSS3手册
  • HTML5手册
  • JavaScript语言提升

    • es补充
    • 事件循环
    • promise基础
    • Promise的链式调用
    • Promise的静态方法
    • async和await
    • Promise相关面试题
  • 网络

    • 客户端与服务器
    • 关于 Apifox 的使用
  • git文档
  • 工程化

    • CommonJS
    • ES module
    • npm文档(包管理)
    • Lass笔记
    • webpack工具
  • canvas详解
  • uinapp笔记
  • 自动化测试
  • oauth2令牌

    • 认识Oauth2
    • 三方应用实现github授权
    • 微信三方应用登录实现
    • 支付宝沙箱支付功能
  • 必看导言

    • 就业的核心问题

      • 课件
    • 表现力的训练

      • 课件
  • 简历制作

    • 课件
    • 简历准备课堂笔记
    • 个人信息课堂笔记
    • 求职意向课堂笔记
    • 技术栈课堂笔记
    • 教育经历课堂笔记
    • 个人优势与评价课堂笔记
    • 工作经历课堂笔记
    • 项目
    • 项目亮难点问题

    • 项目经历

  • 项目准备

    • 课件
    • 课件
  • 技术重点

    • 划重点

    • 非技术环节
  • 简历投递和面试准备

    • 简历投递
    • 面试准备
  • 笔面试环节知识讲解
  • 项目准备
  • 难点攻关
  • 计时器节流问题
luzhichang
2024-09-18
目录

14-面试讲解

# 计时器节流问题

# 面试讲解

# 知识点图谱

  • 浏览器计时节流
  • WebWorker
  • window.URL.createObjectURL
  • Websocket

# 难点描述

**模拟问题:**我看你的简历里面写了有一个亮点是对浏览器计时器节流的处理,并做了封装,这个你能详细说一下吗?

问题分析:

首先应该告诉面试官,是什么样的需求,问题的思考过程,以及解决办法,最后的结果

参考答案:

**(需求描述)**在我们的项目中,有这样子的需求,如果长时间不对页面进行编辑,就自动帮你退出编辑状态。

这个需求刚刚开始做的时候,其实重心是放在和后端沟通,因为需求为了保证当前时间只有唯一用户进行编辑,对当前编辑用户还采用了心跳检测。怎么样发送心跳检测防止多个用户产生同时编辑的情况,当然确定的方案是setInterval轮询的方式(埋钩子:可能会对面试官产生兴趣,既然心跳检测了为什么不直接使用Websocket)

(解决问题)刚开始就打算使用setInterval进行计时,功能这些都没什么问题,但是测试的时候偶尔发现时间不是太准确,虽然我知道使用setInterval做动画的时候计时肯定是不准确的,造成这种情况的问题很多,比较的复杂(埋钩子:引导面试问出你想回答的问题),但是这种长时间不操作的检查,我们并没有要求太严格的时间要求,但是测试发现这个不准确的时候非常的夸张。应该不仅仅是动画计时不准确的原因

最后发现,问题发生在当前页面失活的情况下。查询了相关资料,现代浏览器都是多标签页的情况,为了大量多标签出现,严重影响耗电量和电池续航时间,以及内存的占用。专门处理了相关代码,减少后台工作,而后台运行的计时器就是这种优化的一个手段

简单来说,对于非活动选项卡,它们会自动限制计时器每 1 秒运行一次,而不管代码中指定的原始延迟是多少。例如,如果代码最初使用setInterval()每 50 毫秒运行一次某些代码,一旦应用程序移至后台选项卡,间隔就会自动变为 1000 毫秒(1 秒),随着时间的推移,时间差距也会慢慢拉大。然而,一旦重新激活选项卡,原始间隔或延迟就会返回到原始值。

所以,为了解决这个问题,我使用了WebWorker的API,把计时器直接放在另外的线程中,就不会有这样的问题了,通过主线程与WebWorker线程之间进行通信,发送消息来维持WebWorker线程中计时器的开关。

**(深度思考)**但是这样处理,对于开发其实是有心智负担的,我们的目的其实也就仅仅是通过计时器做简单计时。但是为了解决失活标签页计时器节流的问题,不得不把计时器放入到WebWorker线程,而计时器的开关,我还得通过发送开关消息到WebWorker线程进行处理。

因此我把WebWorker线程做了封装,通过动态生成WebWorker的脚本(埋钩子,引导面试官提问),在主线程劫持模拟setTimeout与setInterval,在WebWorker线程中监听主线程发送的信息,并执行对应的计时器,然后在主线程监听消息,并做出对应处理即可。

这样封装之后,直接在我们的代码中使用计时器即可,没有任何的感觉,不必担心再出现浏览器计时器节流的问题,极大的减少了我们开发的心智负担。

(整个过程就是这样,看面试官您还有什么要问题,我再补充)

# 知识点叙述

1、动态生成WebWorker的脚本

**模拟问题:**你刚刚提到了,动态生成WebWorker的脚本,你是怎么做的?

问题分析:

这个基本上是我们埋下的钩子,引导面试官来问这个问题,也是具体操作的延续

参考答案:

其实主要就是利用了window.URL.createObjectURL(blob) (opens new window)这个API,这个API我们在做上传下载预览的时候经常用到,当然现在的Blob (opens new window)对象需要我们自己创建。然后在主线程劫持模拟setTimeout与setInterval,其实就是覆盖原有的相关方法,内部改成worker.postMessage给WebWorker线程发送数据,并且通过对象缓存记录计时器的回调函数和timer参数,所以发送给WebWorker线程的数据其实就是一个唯一id

在WebWorker线程中监听主线程发送的信息,并执行对应的计时器,同时发送回消息给主线程

主线程接收到消息,通过WebWorker线程计时器不断发送过来的信息,找到缓存对象中的回调函数,进行执行即可

2、Page Visibility API

**模拟问题:**如果当前页签失活了,如何判断当前页签又激活了呢?

问题分析:

一个基础性的问题

参考答案:

直接通过Page Visibility API就行了,在document上添加事件监听addEventListener('visibilitychange', function() {......}),可以通过属性document.visibilityState获取当前的状态是hidden,还是visible

当然,在具体的业务中,页签的反复切换并不能直接确认当前页面是否在编辑状态,需要激活具体的事件才会又重新计时,因此需要对相应的事件进行监听,事件激活之后又重新开始计时。

3、setInterval/setTimeout计时不准确

**模拟问题:**你刚刚说到setInterval/setTimeout计时不准确是什么意思?

问题分析:

这个问题,是故意引导给面试官的一个引导性问题,可以介绍计时器一起卡顿的具体效果原因。

但是,主要目的就是引导面试官去问你想回答的问题,比如:浏览器渲染策略,事件循环等等,

参考答案:

setTimeout、setInterval 属于定时触发器线程属于macrotask,它的回调会受到浏览器渲染、事件循环、http请求等等的影响。

浏览器的画面,是一帧一帧的渲染出来的,每隔一小段时间,会在页面上画一下,只不过画的太快,我们很难感觉出来而已。理想情况下,一秒钟绘画60次,也就是60帧,也就是16.6毫秒画一帧(1000/60)。

setInterval的回调函数并不是到了时间立即执行,而是等系统计算资源空闲下来后才会执行。 下一次触发时间是在setInterval回调函数执行完毕后才开始的

由于计时器的计时并不精确,就可能造成空帧,或者一帧中多次计时到达。所以如果我们用计时器做动画的时候,就有卡顿的感觉。

(当然,具体为什么会计时不准确,那我们需要仔细的去梳理浏览器渲染、事件循环相关的知识点了,面试官你看这个需要详细说一下吗?)

Theme by Vdoing | Copyright © 2021-2024 蜀ICP备2024068710号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式