回答流程化
- 交代背景
- 研究方案
- 方案落地
- 反思
问题一:js超过Number最大值的数怎么处理?
背景:
大数据的计算:金融、科学计算、数据分析
格式展示
用户输入
解决方案:
BigInt
decimal.js
big.js
总结:
bigint来处理大数据
decimal来处理
格式化,格式化成用户好读的格式
表单校验
问题二:如何解决页面请求接口大规模并发问题?
滑动窗口算法,是专门来控制流量的。
背景:
数据采集平台,低代码编辑平台,有序相对稳定发送到后端。
研究方案:
1.请求队列
class RequestQueue{
constructor(maxConcurrent){
this.maxConcurrent = maxConcurrent; //最大并发请求数
this.currentConcurrent = 0; //当前并发请求数
this.queue = []; //请求队列
}
add(request){
return new Promise(resolve,reject) => {
this.queue.push({request,resolve,reject});
this.processQueue();
}
}
processQueue(){
if(this.queue.length > 0 && this.curentConcurrent < this.maxConcurrent){
const {request,resolve,reject} = this.queue.shift();
this.currentConcurrennt++;
request()
.then(request)
.catch(reject)
.finally(()=>{
this.currentConcurrent--;
this.processQueue()'
});
}
}
}
//示例请求函数
function fetchData(url) {
return fetch(url).then(response => response.json());
}
//使用请求队列
const requestqueue = new RequestQueue(5);
const urls = [
' ';
' ';
]
const requests = urls.map(url => () => fetchData(url));
Promise.all(requests.map(request => requestQueue.add(request)))
.then(results => {
console.log('所有请求完成',results);
})
.catch(error => {
console.error('请求失败',error);
});
2.防抖/节流
–防抖(Debounce):确保在指定时间内函数只执行一次,一般取最后一次,常用于输入框的搜索建议。
function Debounce (fun, wait){
let timeout;
return function(...args){
clearTimeout(timeout);
timeout = setTimeout(()=>{
func.apply(this,args);
},wait);
}
}
–节流(Throttle):确保在指定时间间隔内函数执行一次,一般取第一次,常用于窗口的resize,scroll事件。
function throttle(func,limit){
let inThrottle;
return function(...args){
if(!inThrottle){
func.apply(this,args);
inThrottle = true;
setTimeout(()=>inThrottle = false,limit);
}
};
}
3.分页加载
落地、反思:
1.大数据量请求场景下,我们选用了请求队列,我主导封装了请求队列
2.防抖节流,用户交互层面上去解决减少请求的处理
3.分页,滚动加载,可视区绘制。
问题三:请说说大文件上传
背景:之前做xxx产品,我们会涉及到用户自定xxx文件上传。
经常遇到的一些问题:
–网络断开之后,之前传的没了。
–传着传着,网络波动,结果啥都没了。
–关机了,想接着传,做不到。
专业术语:
–断点续传
–断开重连重传
–切片上传
方案:
1.前端切片
2.将切片传递给后端,切片要取名:hash,index
3.后端组合切片
给面试官加料:
–前端切片:主线程做卡顿,web-worker多线程切片,处理完之后交给主进程发送。
–切完后,将blob存储到indexedDB,下次用户进来之后,嗅探一下是否存在未完成上传的切片,有就尝试继续上传。
–websocket,实时通知和请求序列的控制。
–整体说一说我主导这个大文件上传器整体设计:组件设计、props、事件、状态、拖拽上传、多文件选择、通用化不同文件的上传,上传统一协议。
const CHUNCK_SIZE = 5*1024*1024'; //每块大小为5MB
function uploadFile(){
const file = document.getElementById('fileInput').files[0];
if(!file){
alert('Please select a file.');
}
const tatalChuncks = Math.ceil(file.size / CHUNK_SIZE);
let currrentChunk = 0;
function uploadChunck(){
if(currentChunck >= totalChunks){
console.log('upload complete');
return;
}
const start = currentChunck *CHUNK_SIZE;
const end = Math.min(start + CHUNK_SIZE,file.size);
const chunk = file.silce(start,end);
const formData = new FormData():
formData.append('file',chunk);
formData.append('chunkNumber',currentChunk+1);
formData.append('totalChunks',totalChunks);
fetch('/upload',{
method:'POST';
body:formData
}).then(response => {
if(response.ok){
curentChunk++;
uploadChunk();
}else{console.error('Chunk upload faild')};
)}.catch(
error =>{console.error('Upload error',error)}
);
uploadChunk():
}
问题四:在前端怎么实现网页截图
背景:
飞书文档,内容在列表页想要查看
内容导出为png
设计类软件,出图
方案:
截图:
1.canvas
2.puppeteer
3.html2canvas
上传CDN
全页面截图/区域截图/特定区域截图
落地:
–截图工具的时候,需要考虑通用性,‘selector’
–设计具体协议
function takeScreenshot(){
const element = document.getElementById('screenshot-target');
html2canvas(element).then(canvas => {
const img = canvas.toDataUrl('image/png');
const link = document.createElement('a');
link.ref = img;
link.download = 'screenshot.png';
link.click();
});
}
问题五:移动端适配问题如何解决
背景:
项目像支持PC、移动端。
方案:
1.根据不同端来开发不同的页面(成本最高)
2.根据不同端加载不同的CSS样式(可取)
3.根据响应式,来运行不同的样式规则(常用)
4.style预处理器来做
考虑的问题:
1.设置视窗,通过元信息配置 meta
2.掌握媒体查询
3.掌握弹性布局(flex布局)
4.图片响应式
5.视口单位rem/em
问题六:如何修改第三方 npm 包
背景:
来自于设计、产品、老板boss
方案:
1.稳定的库,node_modules,直接改
2.patch方案
‘patch-package’,自动化。
3.fork别人的,直接改源码,改完之后,构建,发布到npm私服。
问题七:使用同一个链接,如何实现PC打开是web应用,手机打开是一个H5应用
背景:
一个链接访问页面,想同时适配PC、Mobile
方案:
1.区分PC、Mobile
–先识别端
js识别,uesrAgent
正则判断
–端内容渲染器(内容加载器)
2.响应式来做
问题八:当QPS达到峰值,该如何处理
背景:
当前端应用的QPS(每秒查询次数)达到峰值时,会对服务器和应用的性能造成很大的压力,甚至可能导致系统崩溃。为了解决这个问题,我们需要采取一系列措施来优化和管理高并发请求。
方案:
1.请求限流
2.请求合并
3.请求缓存
4.任务队列
问题九:如何实现网页加载进度条
拆解:
怎么拿到进度(考虑兼容性、是使用ajax/fetch)
怎么绘制进度:dom、svg
背景:为了提升整站用户加载等待体验,考虑使用加载进度条反馈给给于虎加载过程
方案:
1.页面加载
监听页面加载事件,控制进度条绘制
function simulateLoadingProgress(){
const progressBar = document.getElementById('progress-bar');
let width = 0;
const interval = setInterval(()=>{
if(width >= 100){
clearInterval(interval);
progressBar.style.width = '100%';
setTimeout(()=>{
progressBar.style.display = 'none',
},500);
}else{
width += 10;
progressBar.style.width = width + '%'
}
},200);
}
window.addEventListener('load',()=>{
simulateLoadingProgress();
})
2.请求实现
function loadResource(url){
const xhr = new XMLHttpRquest();
xhr.open('GET'.url,true);
xhr.onprogress = function(event){
if(event.lengthComputeable){
const percentComplete = (event.loaded / even.total)*100;
document.getElementById('progress-bar').style.width = percentComplete + '%';
}
};
xhr.onload = function(){
if(xhr.status ===200){
document.getElementById('progress-bar').style.width = 100%;
setTimeout(()=>{
document.getElementById('progress-bar').style.display = 'none';
},500)
}
};
xhr.send();
}
window.addEventListener('load',()=>{
loadResource('http://example.com/large-file')
})
fetch不可以这样子!!
问题十:了解过前端水印功能吗?
背景:
为了保证用户隐私,数据相对安全,实现水印,飞书(名字)waterMar
文档保护/图片保护/视频保护
方案:
明水印:
背景添加水印
内容生成,svg
function createmarkSVG(text){
const svg = '
<svg xmlns = "http://www.w3.org/2000/svg" width="200" viewBox="0 0 200 200">
<text x="50%" y="50%" dy=".35em" text-anchor="middle" fill="rgba(0,0,0,0.1)" font-size="30" transform="rotate(-45,100,100)">
${text}
</text>
</svg>
';
return 'data:image/svg+xml;base64,${btoa(svg)}';
}
const watermarkText = "Confidential";
document.body.style.backgroundImage = 'url('${createWatermarkSVG(watermarkText)}')';
图片水印 canvas
function addWatermark(imgsrc,watermarkText){
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const image = new Image();
image.src = imageSrc;
image.onload = function(){
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image,0,0);
ctx.font = '30px Arial';
ctx.fillstyle = 'rgba(255,255,255,0.5)';
ctx.fillText(watermarkText,image.width - 150,image.height - 30);
const watermarkedImage = document.getElementById('watermarkedImage');
watermarkedImage.src = canvas.toDataUrl('image/png');
};
}
const imageSrc = document.getElementById('sourceImage').src;
addWatermark(imageSrc,'Confidential');
暗水印:
黑科技,将信息写入到文件二进制代码里去。
问题十一:web应用中如何对静态资源加载失败的场景做降级处理
背景:
图片/css文件/javascript文件/CDN/字体文件/服务端渲染失败
方案:
图片:
1.占位图,alt来描述图片
2.重试机制(404/无权限)
3.上报
<img src="imagejpg" alt="Example Image" onerror="handleImageError(this)">
function handleImageError(image){
image.onerror = null: //防止死循环
image.src = 'placeholder.jpg';//使用占位图
}
css文件处理:
资源没加载到:
1.关键样式,通过内联
2.备用样式
3.上报
<link rel="stylesheet" href="style.css" onerror="handleCssError()">
function handleCssError(){
//加载备用样式
const fallbackCss = document.createElement('link');
fallbackCss.rel = 'stylesheet’;
fallbackCss.href = 'fallback-style.css';
document.head.appendChild(fallbacks);
}
javascript文件处理:
网络异常,导致资源没加载:
1.内联脚本
2.备用脚本处理
3.上报
CND:
1.本地备份,如果cdn出错了,就使用本地备份
2.动态切换,切换到另一个有用的cdn服务
字体:
1.使用降级字体 apple、微软雅黑
2.webfont处理字体
ssr:
1.降级的html用作渲染
2.切换为客户端渲染
问题十二:怎样设计一个全站请求耗时统计工具
背景:
通过统计工具,可以更清晰地看到整个站点性能情况,首屏加载时间(FP/FCP)
1.监控请求耗时:HTTP、中间件,axios
2.前端监控,监控整个请求,记录耗时数据
3.后端监控:
4.数据汇总:数据清洗加工,数据可视化,可视化图表
方案:
问题十三:请说说你对函数式编程思想的理解
函数式编程的基本概念:
1.函数为一等公民,函数封装的方式解决问题
2.纯函数,没有任何副作用,相同输入(参数)得到相同输出(返回值)
3.不可变性,
4.高阶函数,函数柯里化
5.函数组合,类似于面向对象继承
总结优点:
1.可测试性,更好写单元测试
2.可维护性
3.并发
4.简洁
问题十四:请说说你对DNS协议的理解:(对应需要复习计算机网络)
将域名映射到IP上
域名解析整个过程:
1.用户输入,解析域名
2.检查自身DNS缓存
3.操作系统DNS缓存
4.本地域名服务器
5.根据本地DNS服务器去查找根DNS服务器、顶级域名服务器(TLD)、权威DNS服务器
6.返回结果,浏览器缓存并向IP发送请求
DNS记录类型:
1.A记录:将域名映射到IPv4地址
2.AAAA记录:将域名映射到IPv6地址
3.CNAME:将域名映射到另外一个域名
4.MX记录:知道邮件服务器
5.TXT:文本信息存储,域名验证,SPF记录
DNS常见问题:
1.DNS解析慢:DNS预解析/使用CDN,CDN节点用户就近/减少外部资源请求,自己域名+oss+cdn
2.DNS劫持:HTTPS,证书保证传输安全性/DNSSEC:DNS安全扩展
3.优化:DNS缓存/nslookup/dig/在线:dns.google.com
问题十五:我们是美团电影的,请问怎么实现一个电影票选座功能
使用canvas来实现选座功能
思路:
1.canvas基础处理
2.座位绘制
3.交互添加
4.座位状态管理,数据结构设计
5.优化,用户体验升级
问题十六:请说说图片性能优化的方案
方案:
1.loading=“lazy”
2.intersection observer检测是否已经到了视窗
3.滚动事件,监听scroll事件,最原始的做法
4.使用库
问题十七:移动端上拉加载,下拉刷新实现方案
背景:
长列表,需要通过上拉加载提升性能。
用户在页面顶部向下拉时,触发页面重新渲染
方案:
上拉加载:
1.滚动事件监听
2.怎么判断触底
3.回调触发列表加载更多
下拉刷新:
1.监听触摸事件,touch、tap
2.显示刷新指示器,显示有没有达到下拉阈值。
3.触发刷新操作
考虑的点:
1.性能优化:节流/防抖
2.用户体验:视觉反馈,下拉刷新的指示器/平滑动画/错误处理
3.兼容:触摸事件/CSS hack
问题十八:深度SEO优化,你都知道哪些细节
SEO优化思路:
1.页面结构优化:语义化标签
2.内容优化:保证页面中关键词的覆盖率
3.技术向SEO优化:站点地图、结构化数据、
问题十八:windows对象上频繁绑定内容,有什么风险
风险分析:
1.命名冲突
2.全局污染
3.安全风险
4.性能问题,增加内存开销
解决方案:
1.模块化
2.命名空间
3.IIFE(形成闭包,形成独立作用域)
4.开启严格模式
5.了解qiankun的快照沙箱实现原理
问题二十:小程序的双线程架构了解吗
双线层:
1.逻辑层(App Service):运行在JavaScriptCore引擎中,负责小程序业务逻辑;数据、时间、网络;不能直接操作视图,需通过通信机制。
2.渲染层(View):运行在WebView中,负责页面渲染;接收逻辑层UI更新指令;独立webview,并行渲染多个页面
双线层的交互:
优化思路:
1.分离业务逻辑和渲染逻辑
2.更新UI通过异步方式
3.并行页面处理,提升切换速度