记一次面试被面试官问的问题(惨败)

一、http中的强缓存和协商缓存分别是什么,有什么区别?

答:这个问题没有想到会问,以为前端不会问道这些网络相关的问题。网上搜到的总结一下;先解释缓存是什么,再逐一回答;

浏览器缓存(Brower Caching)是浏览器对之前请求过的文件进行缓存,以便下一次访问时重复使用,节省带宽,提高访问速度,降低服务器压力
http缓存机制主要在http响应头中设定,响应头中相关字段为Expires、Cache-Control、Last-Modified、Etag。
简而言之,就是告诉浏览器在约定的这个时间前,可以直接从缓存中获取资源(representations),而无需跑到服务器去获取。

强缓存

强缓存‌是指浏览器在访问某个资源时,直接从本地缓存中读取数据,而不需要向服务器发送请求。强缓存的实现主要依赖于HTTP响应头中的Cache-ControlExpires字段。

  • ‌Cache-Control‌:通过设置Cache-Control响应头,服务器可以指定缓存的行为和策略。常见的指令包括max-age(指定缓存时间)、no-cache(不使用强缓存,但仍会使用协商缓存)、no-store(不使用缓存)等。例如,Cache-Control: max-age=31536000表示资源在一年内有效,浏览器可以直接使用缓存‌
  • ‌Expires‌:这是HTTP 1.0规范中的字段,用于指定资源的过期时间。当浏览器发起请求时,如果本地缓存未过期,浏览器将直接使用缓存副本,而无需再次请求服务器‌

协商缓存

‌协商缓存‌是指浏览器在访问资源时,首先向服务器发送请求,服务器根据请求中的某些标识(如Last-ModifiedETag)来判断资源是否发生变化。如果资源未变化,服务器返回304状态码,浏览器继续使用本地缓存;如果资源有更新,服务器返回最新的资源数据。

  • ‌Last-Modified‌:服务器在响应头中返回资源的最后修改时间。当浏览器再次请求资源时,通过If-Modified-Since请求头将上次的最后修改时间发送给服务器。如果资源的最后修改时间与服务器上的相同,服务器返回304状态码‌23。
  • ‌ETag‌:这是一个更精确的版本控制标识,通常是一个哈希值。当资源变化时,ETag也会变化。服务器通过If-None-Match请求头发送ETag给服务器,如果ETag未变化,服务器返回304状态码‌

应用场景

强缓存适用于内容变动不频繁的资源,如图片、CSS和JavaScript文件等;协商缓存适用于内容变动频繁的资源,如新闻文章、产品详情页等

二、怎么处理同一个接口在重复请求之后(比如三次),才拿到了对应的结果,怎么解决多次请求的问题?

答:这个面试问题也没有想到。。

 

  • 首先,创建一个对象来存储正在进行的请求。可以使用Map数据结构,其中键是请求的唯一标识(例如请求的 URL 和参数等组合成的字符串),值是对应的CancelToken(用于取消请求)。
  • 在请求拦截器中,对于每个请求,检查是否已经存在相同的请求正在进行中。

 

 

 1   const pendingRequests = new Map();
 2   import axios from 'axios';
 3    axios.interceptors.request.use((config) => {
 4        const requestKey = config.url + JSON.stringify(config.params);
 5        if (pendingRequests.has(requestKey)) {
 6            // 如果请求已经存在,取消当前请求
 7            const cancelToken = pendingRequests.get(requestKey);
 8            cancelToken.cancel('重复请求已取消');
 9        } else {
10            // 创建一个新的CancelToken
11            const source = axios.CancelToken.source();
12            config.cancelToken = source.token;
13            // 将请求添加到正在进行的请求列表中
14            pendingRequests.set(requestKey, source);
15        }
16        return config;
17    }, error => {
18        return Promise.reject(error);
19    });

 

  • 在响应拦截器中,当请求完成后,需要从pendingRequests对象中移除对应的请求。

 

 1  axios.interceptors.response.use((response) => {
 2        const requestKey = response.config.url + 
 3    JSON.stringify(response.config.params);
 4        if (pendingRequests.has(requestKey)) {
 5            // 请求完成,从正在进行的请求列表中移除
 6            pendingRequests.delete(requestKey);
 7        }
 8        return response;
 9    }, error => {
10        const requestKey = error.config.url + JSON.stringify(error.config.params);
11        if (pendingRequests.has(requestKey)) {
12            // 请求出错,从正在进行的请求列表中移除
13            pendingRequests.delete(requestKey);
14        }
15        return Promise.reject(error);
16    });

 

 上面这种方法时通过识别判断url 是否重复,然后使用axios.CancelToken 取消掉相同的请求。

  还有别的方法比如记录存储请求时的key ,再发送新请求时判断是否相同的key在处理, 然后取消请求或者选择等待; 在响应拦截的时候删除掉那个key

 

posted @ 2024-12-07 21:13  peter_sdl  阅读(48)  评论(0)    收藏  举报