目录
async await promise try...catch
怎么判断localStorage存满了?
(1)JSON.stringify(localStroage).length和5m上限比较
(2)遍历每个item,之后根据getItem(item).lenght 判断长度 之后把长度全部加起来, 之后进行1024计算 看超过没超过5兆
// 得到localStorage已使用容量
(function(){
if(!window.localStorage) {
console.log('浏览器不支持localStorage');
}
var size = 0;
for(item in window.localStorage) {
if(window.localStorage.hasOwnProperty(item)) {
size += window.localStorage.getItem(item).length;
}
}
console.log('当前localStorage已使用容量为' + (size / 1024).toFixed(2) + 'KB'); // 再除以1024,就是M单位
})()
(3)onerror监控 \try catch (LocalStorage的异常处理)
当达到localStorage容量上限时,会抛出 QUOTA_EXCEEDED_ERR(
各浏览器不一样)
const QUOTA_EXCEEDED_ERR_CODE = 22 //Chrome
function write (key, data) {
try {
localStorage.setItem(key, data); //写入数据
} catch (e) {
if (e.code === QUOTA_EXCEEDED_ERR_CODE) {
localStorage.clear();
localStorage.setItem(key, data);
}
}
}
怎么避免 localStorage 存满的问题?
1、划分域名。各域名下的存储空间由各业务组统一规划使用
2、跨页面传数据:考虑单页应用、优先采用 url 传数据
3、最后的兜底方案:清掉别人的存储
localStorage的方法getItem、setItem、removeItem、clear...
//核心localStorage管理代码,对localStorage进行模块化为了将错误信息以JSON格式记载。
define(function() {
var METHOD = {
GET : 0,
SET : 1,
REMOVE : 2,
CLEAR : 3
},
_localStorageFactory = function(method, key, value) {
if(localStorage) {
switch(method) {
case METHOD.GET:
return localStorage.getItem(key);
case METHOD.SET:
localStorage.setItem(key, value);
break;
case METHOD.REMOVE:
localStorage.removeItem(key);
break;
case METHOD.CLEAR:
localStorage.clear();
break;
}
return true;
}
return false;
};
return {
getItem : function(type, key) {
var item = JSON.parse(_localStorageFactory(METHOD.GET, type));
if(item) {
return item[key];
}
return null;
},
setItem : function(type, key, value) {
var item = JSON.parse(_localStorageFactory(METHOD.GET, type));
if(!item) {
_localStorageFactory(METHOD.SET, type, '{"' + key + '": ' + JSON.stringify(value) + '}');
} else {
item[key] = value;
_localStorageFactory(METHOD.SET, type, JSON.stringify(item));
}
},
removeItem : function(type, key) {
var items = _localStorageFactory(METHOD.GET, type);
delete items[key];
_localStorageFactory(METHOD.SET, type, items);
},
clear : function(type) {
_localStorageFactory(METHOD.REMOVE, type);
},
clearAll : function() {
_localStorageFactory(METHOD.CLEAR);
}
};
});
async await promise try...catch
async function buildData(name) {
try {
let response1 = await axios.get('/api/user?name=' + name);
let userInfo = response1.data;
let response2 = await axios.get('/api/topics?user_id' + userInfo._id);
let posts = response2.data;
// i got it.
} catch(err) {
console.log(err);
}
}
buildData('xiaoming');
如果在失效时间前修改了强缓存的文件,怎么让强缓存也更新
(1)手动清除缓存、自动推送资源
(2)webpack打包文件名加上hash(版本号/时间),强缓存失效内更改,就会重新请求。发现url中的hash值变化了,就重新强缓存。 (url不允许改变)
采用webpack设置入口文件index.html的cache-control为no-cache,即入口文件不使用强缓存,只使用协商缓存,其他文件可使用强缓存,这样尽管发请求,还在强缓存过期时间内,也会拉取最新的资源
(3) 给静态资源都带上版本号,每次请求如果版本号改了,会请求新的资源的,但是index.html别做缓存
webpack打包生成文件名
output参数的 - filename属性,表示的是如何命名生成出来的入口文件
chunkFilename属性,指定的是除入口文件外的chunk的命名(这些chunk通常是由于webpack对代码的优化所形成的,比如因应实际运行的情况来异步加载)。
规则有以下三种:
- [name],指代入口文件的name,也就是entry参数的key,因此可以在name里利用
/
,即可达到控制文件目录结构的效果。 - [hash],指代本次编译的一个hash版本,每一次打包都会生成一个唯一的 hash;在缓存的层面来说,相当于一次全量的替换。
- [chunkhash],指代的是当前chunk的一个hash版本,在两次编译中,如果某个chunk根本没有发生变化,那么该chunk的hash也就不会发生变化。这在缓存的层面上来说,就是把缓存的粒度精细到具体某个chunk,只要chunk不变,该chunk的浏览器缓存就可以继续使用。
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].' + Version + '.js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].' + Version + '.js')
},
给没有生成的元素绑定事件
用事件代理(事件冒泡)
默认情况下,事件使用冒泡事件流,不使用捕获事件流。在Firefox和Safari里,可以显式的指定使用捕获事件流,方法是在注册事件时obj.addEventListener(evtype,fn,useCapture)传入useCapture参数,将这个参数设为true。(从根元素到被点击的元素,从上到下)
js异步处理除了async和defer还有什么
异步加载或许还有webpack的懒加载
还可以用一个方法动态创建script标签,在load事件触发时回调这个方法
前端性能监控
本地:谷歌的performance.timing ( Navigation Timing API )(合成监控 - 模拟)
(2)真实用户监控(RUM):
100w个用户,怎么检测用户性能(回答前端监控,埋点
前端监控可以分为三类:数据监控、性能监控和异常监控。
常见的性能监控数据包括:
- 不同用户,不同机型和不同系统下的首屏加载时间
- 白屏时间
- http等请求的响应时间
- 静态资源整体下载时间
- 页面渲染时间
- 页面交互动画完成时间
实现前端监控的步骤为:前端埋点和上报、数据处理和数据分析。
常见的前端埋点方法分为三种:代码埋点、可视化埋点和无痕埋点。
(1)代码埋点,就是以嵌入代码的形式进行埋点,比如需要监控用户的点击事件,会选择在用户点击时,插入一段代码,记录这个监听行为或者将监听行为以某一种数据格式直接传递给server端。此外比如需要统计产品的PV和UV的时候,需要在网页的初始化时,发送用户的访问信息等。
优点:可以在任意时刻,精确的发送或保存所需要的数据信息。
缺点:工作量较大,每一个组件的埋点都需要添加相应的代码
(2)可视化埋点,提供一个可视化系统,输入为业务代码,可以在业务代码中自定义的增加埋点事件等等,最后输出的代码耦合了业务代码和埋点代码。(用可视化交互的手段代替代码埋点)
也就是用一个系统来实现手动插入代码埋点的过程。
缺点:可视化埋点可以埋点的控件有限,不能手动定制。
(3)无埋点(全部埋点),是前端的任意一个事件都被绑定一个标识,所有的事件都记录下来。通过定期上传记录文件,配合文件解析,解析出来我们想要的数据,并生成可视化报告。。
比如从页面的js代码中,找出dom上被绑定的事件,然后进行全埋点。
优点:由于采集的是全量数据,所以产品迭代过程中不需要关注埋点逻辑,也不会出现漏埋、误埋等现象。
缺点:
- 无埋点采集全量数据,给数据传输和服务器增加压力
- 无法灵活的定制各个事件所需要上传的数据
采集真实用户性能数据:
- 使用标准的 API;
- 定义合适的指标;
- 采集正确的数据;
- 上报关联的维度。
navigator.sendBeacon
大部分现代浏览器都支持 navigator.sendBeacon 方法。这个方法可以用来发送一些统计和诊断的小量数据,特别适合上报统计的场景。