4399前端面试总结

7,008 阅读6分钟

昨天去面试了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 的区别

这个问题我有了解过,但面试的时候回答的不太清楚,说的有点笼统

setTimeoutpromise 两者都可以用来处理异步操作,先上一张图说明同步任务和异步任务是怎样执行的

执行机制
执行机制
从图中可以看出,异步任务会先进入Event Table注册回调函数到Event Queue,等待主线程的同步任务全部执行完毕后,进入到主线程执行。那问题来了,setTimeout 和 promise都是异步任务,两者有什么区别呢?这就引出了宏任务与微任务的区别

什么是宏任务和微任务

还是先上一幅图,太能说明问题了

宏任务与微任务
宏任务与微任务

上文说的Event Queue事件队列有分宏任务和微任务 常见的宏任务有scriptsetTimeoutsetInterval,微任务有promiseprocess.nextTick

给一个例子解析一下执行流程

setTimeout(function() {
    console.log('setTimeout');
})

new Promise(function(resolve) {
    console.log('promise');
}).then(function() {
    console.log('then');
})

console.log('console');

这段代码作为宏任务进入主线程,从上往下读取

  • 首先读取到setTimeout,将其回调函数注册并分发到宏任务事件队列
  • 接下来遇到Promisenew 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的知识。比如怎样实现登录权限、当没有权限时怎样处理.. .感觉自己回答的不太好,因为我项目经验比较少,没有碰到类似的场景。总的来说,这次面试给我的感受是,自己无论是基础还是实践经验都是比较缺乏的,等我深入学习一段时间再来补充剩下的内容吧。