昨天去面试了4399公司前端岗位,这应该是我第二次面试吧,没有进入二面,有点难受。面试完个人感觉挺良好的,但回去总结发现面试官问的问题我很多都回答错了。。。还是得继续努力,希望能早日拿到心仪的offer。下面总结一下这次面试的题目。
目录
-
强制缓存与协商缓存的区别
-
setTimeout 和 promise 的区别
-
Cookie 和 Session 的区别
-
Vue怎样实现登陆拦截
-
Vue导航守卫是什么
强制缓存与协商缓存的区别
当面试官问道这个题目时,我是有点蒙的,以为问的是本地存储技术,然后我就说了 localstorge、sessionstorge、indexDB。。。
网上找到的一张图,很好的说明了浏览器缓存机制
什么是强制缓存
浏览器在发送请求时,会先去获取该资源缓存的header信息,若命中强缓存信息(cache-control 或 expires),浏览器就会直接从浏览器取资源,而不向浏览器发送请求了,返回的状态码是200 OK (from memory cache)或200 OK (from disk cache);
-
max-age 根据该值计算一个资源过期时间,如果请求时间在过期时间之前,则命中缓存
-
no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
-
no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
-
public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
-
private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。
什么是协商缓存
协商缓存是浏览器通过发送请求让服务器告知浏览器缓存是否可用,请求会携带第一次请求返回的有关缓存的header字段信息(Last-Modified/If-Modified-Since 和 Etag / If-None-Match)。由服务器根据请求中的相关header信息来比对结果是否协商缓存命中,若命中浏览器会返回新的 header 信息更新缓存中对应的header信息,但是不会返回资源内容。
setTimeout 和 promise 的区别
这个问题我有了解过,但面试的时候回答的不太清楚,说的有点笼统
setTimeout
和 promise
两者都可以用来处理异步操作,先上一张图说明同步任务和异步任务是怎样执行的
Event Table
注册回调函数到Event Queue
,等待主线程的同步任务全部执行完毕后,进入到主线程执行。那问题来了,setTimeout 和 promise都是异步任务,两者有什么区别呢?这就引出了宏任务与微任务的区别
什么是宏任务和微任务
还是先上一幅图,太能说明问题了
上文说的Event Queue
事件队列有分宏任务和微任务
常见的宏任务有script
,setTimeout
,setInterval
,微任务有promise
,process.nextTick
给一个例子解析一下执行流程
setTimeout(function() {
console.log('setTimeout');
})
new Promise(function(resolve) {
console.log('promise');
}).then(function() {
console.log('then');
})
console.log('console');
这段代码作为宏任务进入主线程,从上往下读取
- 首先读取到
setTimeout
,将其回调函数注册并分发到宏任务事件队列 - 接下来遇到
Promise
,new promise
会立刻执行,将then
回调函数分发到微任务队列 - 最后遇到
console
,立刻执行输出 - 第一个宏任务执行结束后,进入当前微任务事件队列,执行输出,第一次事件循环结束
- 开启第二次循环,首先读取宏任务队列...
所以这段代码输出顺序: promise,console,then,setTimeout
Cookie 和 Session 的区别
当面试官问起 session 和 Cookie 的区别是,我回答了 sessionStorage 和 cookie 的区别,因为之前没有了解过 Session
Cookie大家应该都比较清楚,它可以将数据存放在客户端上,在请求时发送到服务器,可以用来存储用户信息或进行身份验证等;而session数据是放在服务器上,两者之间主要的区别如下:
-
cookie不是很安全,别人可以分析存储到本地的cooike并对服务器进行欺骗,若考虑安全问题应当使用 session
-
session会在一定时间内保存在服务器上。当访问增多,会比较占用服务器的性能
-
使用cookie保存数据有数量限制
所以我觉得,最佳实践应该是根据业务需求,两者结合一起使用
Vue怎样实现登陆拦截
Vue导航守卫拦截
思路:在路由准备跳转时,使用使用 router.beforeEach
注册一个全局前置守卫,判断跳转路由是否需要登录权限
第一步 添加路由权限
const routes = [
{
path: '/',
name: '/',
component: Index
},
{
path: '/repository',
name: 'repository',
meta: {
requireAuth: true, // 添加该属性,表示进入这个路由是需要登录的
},
component: Repository
},
{
path: '/login',
name: 'login',
component: Login
}
];
第二步 使用VUE导航守卫
router.beforeEach((to, from, next) => {
if (to.meta.requireAuth) { // 判断该路由是否需要登录权限
if (store.state.token) { // 通过vuex state获取token是否存在
next();
}
else {
next({
path: '/login',
query: {redirect: to.fullPath} // 将跳转的路由path作为参数,登录成功后跳转到该路由
})
}
}
else {
next();
}
})
这种登录拦截有两个缺点:
- 是简单的前端路由控制,并不能真正阻止用户访问需要登录权限的路由
- 当token失效了,但是token依然保存在本地
所以这时候需要结合http拦截器和后端返回的状态码来判断
使用axios拦截器拦截http请求和响应
思路: 当后端接口发现token过期,返回 401 Unauthorized
,让用户重新登录
// http request 拦截器
axios.interceptors.request.use(
config => {
if (store.state.token) { // 判断是否存在token,如果存在的话,则每个http header都加上token
config.headers.Authorization = `token ${store.state.token}`;
}
return config;
},
err => {
return Promise.reject(err);
});
// http response 拦截器
axios.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
// 返回 401 清除token信息并跳转到登录页面
store.commit(types.LOGOUT);
router.replace({
path: 'login',
query: {redirect: router.currentRoute.fullPath}
})
}
}
return Promise.reject(error.response.data) // 返回接口返回的错误信息
});
Vue导航守卫是什么
“导航”表示路由正在发生改变,可以通过观察 $route 对象来应对这些变化。
总结
因为我简历写了VUE框架,所以面试官为了挺多关于VUE的知识。比如怎样实现登录权限、当没有权限时怎样处理.. .感觉自己回答的不太好,因为我项目经验比较少,没有碰到类似的场景。总的来说,这次面试给我的感受是,自己无论是基础还是实践经验都是比较缺乏的,等我深入学习一段时间再来补充剩下的内容吧。