2025前端面试及答案

331 阅读7分钟
1. 请求失败会弹出一个 toast,如何保证批量请求失败,只弹出一个 toast
方法一:使用全局标志位

let isToastShown = false; // 全局标志位
 
function makeRequests() {
    const requests = [
        fetchPost(),
        fetchComments()
    ]; // 多个请求
 
    Promise.all(requests)
        .then(() => {
            // 所有请求成功的处理逻辑
        })
        .catch(errors => {
            if (!isToastShown) {
                // 检查标志位
                notify(errors[0]); // 弹出 toast
                isToastShown = true; // 设置标志位为 true
            }
        });
}
 
function fetchJSON(url, input) {
    return fetch(url, input)
        .then(res => {
            if (res.ok) {
                return res.json();
            }
            const err = new HttpError(res);
            if (!isToastShown) { // 检查标志位
                notify(err); // 弹出 toast
                isToastShown = true; // 设置标志位为 true
            }
            throw err; // 确保错误被抛出,否则后续逻辑可能无法捕获
        });
}
 
// 示例错误类
class HttpError extends Error {
    constructor(response) {
        super(`${response.status} ${response.statusText}`);
        this.name = "HttpError";
        this.response = response;
    }
}
 
// 重置标志位(在新的请求开始前)
makeRequests().finally(() => {
    isToastShown = false; // 确保在下一次请求时标志位被重置
});
方法二:使用防抖函数

JavaScript

// 防抖函数
function debounce(fn, delay = 1000) {
    let timeout;
    return function (...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            fn.apply(this, args);
        }, delay);
    };
}
 
const notifyDebounced = debounce(message => {
    notify(message);
}, 3000); // 3 秒内只执行一次
 
// 示例调用
fetchJSON(url, input)
    .catch(err => {
        notifyDebounced(err); // 使用防抖后的通知函数
    });
方法三:集中处理错误

JavaScript

function makeRequests() {
    const requests = [
        fetchPost(),
        fetchComments()
    ]; // 多个请求
 
    Promise.allSettled(requests)
        .then(results => {
            const hasError = results.some(result => result.status === "rejected");
            if (hasError) {
                const firstError = results.find(result => result.status === "rejected").reason;
                notify(firstError); // 合并所有错误并只弹出一次
            } else {
                // 所有请求成功的处理逻辑
            }
        });
}
2.如何减少项目里面 if-else
  1. 使用条件(三元)运算符
  2. 使用对象或数组查找
  3. 使用switch语句
  4. 使用逻辑运算符简化条件判断
  5. 使用Map或Set等数据结构进行查找(对于复杂数据)
3.如何标准化处理线上用户反馈的问题
  1. 设立统一的反馈入口 在应用中提供一个明显的“反馈”按钮或链接,让用户能够轻松找到反馈的途径。 反馈入口可以是弹窗、侧边栏、页脚或固定的悬浮按钮。
  2. 设计反馈表单 表单应该简单明了,只收集必要的信息。 包括字段如:问题描述、联系方式(可选)、截图(可选)、设备信息等。 提供分类选项,让用户选择反馈类型(如:功能问题、界面问题、建议等)。
  3. 收集上下文信息 自动收集用户操作路径、浏览器信息、操作系统、网络状态等,无需用户手动填写。 对于技术问题,收集console日志和错误信息。
  4. 反馈处理流程 设立一个明确的问题跟踪和分类机制。 使用工单系统(如Jira、Trello、GitHub Issues等)管理反馈。 为每个反馈分配唯一的追踪ID,方便用户和开发者跟踪问题状态。
  5. 自动化响应 对于常见问题,可以设置自动回复模板,减少客服工作量。 确认收到反馈的自动回复中包含追踪ID。
  6. 问题分类和优先级 根据问题类型和严重性进行分类,并设定优先级。 严重问题需要优先处理,并可能触发紧急响应流程。
  7. 定期审查和反馈 定期审查反馈的处理情况,确保问题得到妥善解决。 向用户提供问题处理的进度更新或最终解决方案。
  8. 用户反馈闭环 问题解决后,通知用户并询问是否满意解决方案。 收集用户的后续反馈,持续优化产品。
  9. 数据分析和报告 分析用户反馈数据,识别产品和服务的常见问题。 定期生成报告,为产品改进提供依据。
  10. 培训和支持 培训客服团队,确保他们了解如何有效处理用户反馈。 提供技术支持,帮助解决复杂的用户问题。
  11. 文档化和知识库 将问题和解决方案文档化,建立知识库。 知识库可以帮助快速解决重复出现的问题
4.px 如何转为 rem
  1. 使用 Stylus 工具: 如果你使用 Stylus 作为 CSS 预处理器,可以使用 stylus-px2rem 工具来自动将 px 转换为 rem。首先需要安装该工具:npm install stylus-px2rem --save-dev。然后在你的 Stylus 文件中引用该工具,并编写 CSS 规则。Stylus 会将 px 单位自动转换为 rem 单位。
  2. 使用 PostCSS 插件: 在 Vue 或其他 JavaScript 项目中,可以使用 PostCSS 插件如 postcss-pxtorem 来实现 px 到 rem 的转换。首先需要安装相关依赖:npm install postcss-pxtorem postcss-loader --save-dev。接着在项目的根目录下创建或编辑 postcss.config.js 文件,配置插件参数。在样式文件中直接使用 px 单位,PostCSS 会自动将其转换为 rem 单位。
  3. 使用 flexible.js: 这个方法适用于移动端适配。首先下载并引入 lib-flexible.js,该脚本会根据视口宽度动态设置 html 元素的字体大小。然后可以使用 px-to-rem 插件或手动设置转换函数,将 px 值转换为 rem 值。这种方法结合了媒体查询和动态字体大小调整,能够实现更灵活的响应式设计。

px 和 rem 的换算规则

  • px(像素): px 是一种绝对单位,代表屏幕上的实际像素点。例如,如果某个元素的宽度设置为 300px,那么无论在任何设备上,这个元素的宽度都会占据 300 个像素点的空间。
  • rem(相对单位): rem 基于根元素的字体大小进行换算。例如,如果根元素字体大小为 16px,那么 1rem 就等于 16px。如果在 CSS 中显式设置了根字体大小,例如 html{font-size:20px;},那么 1rem 就等于 20px。

通过以上方法,可以将 px 单位有效地转换为 rem 单位,从而实现更灵活和响应式的布局设计。

5.浏览器有同源策略,但是为何 cdn 请求资源的时候不会有 跨域限制

浏览器的同源策略确实限制了不同源之间的资源交互,但CDN请求资源时不受跨域限制的原因主要在于CDN的工作机制和配置方式。

  1. CDN的工作原理:CDN(内容分发网络)是一种分布式网络服务,其核心功能是缓存和分发静态资源(如图片、CSS、JavaScript等)。这些资源通常存储在CDN节点上,用户请求时直接从最近的节点获取资源,而不需要经过浏览器的同源策略检查。因此,CDN请求资源时不会受到浏览器同源策略的限制。
  2. 跨域资源共享(CORS)  :虽然浏览器的同源策略限制了浏览器脚本与不同源资源的交互,但通过CORS机制,服务器可以明确允许跨域请求。例如,CDN可以通过设置HTTP响应头(如Access-Control-Allow-Origin)来允许特定域名的跨域请求。这种方式适用于动态数据的跨域请求,而静态资源的加载则不需要额外的CORS配置。
  3. 静态资源加载的特殊性:静态资源(如图片、CSS、JavaScript文件)通常不会触发浏览器的同源策略限制。这是因为浏览器在加载这些资源时,主要关注的是协议、域名和端口是否一致,而不是脚本的执行权限。因此,CDN上的静态资源可以直接被浏览器加载,而无需额外的跨域处理。
  4. CDN缓存策略:CDN缓存机制进一步简化了跨域问题。当用户请求资源时,CDN节点会根据缓存策略返回本地缓存的内容,而无需经过浏览器的同源策略检查。这种方式不仅提高了加载速度,也避免了跨域限制的问题。

CDN请求资源时不受跨域限制的原因在于其工作原理和配置方式的独特性。静态资源的加载不需要跨域处理,而动态数据的跨域请求可以通过CORS机制实现。这些机制共同确保了CDN能够高效地分发资源,同时避免了浏览器同源策略的限制。