面试题手册

梳理高频技术问题,帮助你按主题复习和查漏补缺。

服务端阅读 05月29日 22:54

axios 如何实现并发请求和取消请求?代码怎么写?

axios 的并发和取消分别基于 Promise.all 和 AbortController/CancelToken。并发请求: 使用 Promise.all 同时发起多个请求,全部成功返回结果数组,任一失败则整体失败。axios.all 已废弃(v0.27+),直接用 Promise.all。需要逐个处理结果用 Promise.allSettled,无论成功失败都返回每个请求的状态。// 并发请求const [users, posts] = await Promise.all([ axios.get('/api/users'), axios.get('/api/posts')]);// 容错并发const results = await Promise.allSettled([ axios.get('/api/a'), axios.get('/api/b')]);results.forEach(r => { if (r.status === 'fulfilled') handleData(r.value.data);});取消请求: 新方案用 AbortController(v0.22+推荐),旧方案 CancelToken 已废弃。AbortController 是浏览器原生 API,与 fetch 通用。// AbortController 取消const controller = new AbortController();axios.get('/api/data', { signal: controller.signal });// 取消controller.abort();// 封装自动取消:同一接口新请求自动取消旧请求const pending = new Map();function fetchWithCancel(url) { pending.get(url)?.abort(); const ctrl = new AbortController(); pending.set(url, ctrl); return axios.get(url, { signal: ctrl.signal }).finally(() => pending.delete(url));} 追问: Promise.all 和 Promise.allSettled 在错误处理上的区别是什么? 如何控制并发数量(如最多同时 3 个请求)? 取消请求后 axios 抛出的是什么错误?如何区分取消和真正的请求失败? 路由切换时如何批量取消未完成的请求? CancelToken 为什么被废弃?它和 AbortController 的实现原理有什么不同?
服务端阅读 05月29日 22:54

axios 文件上传下载怎么做?进度监控和 CSRF 防护如何实现?

axios 的高级特性主要有 文件上传下载、进度监控、CSRF 防护、实例封装。文件上传: 使用 FormData 构建请求体,设置 Content-Type: multipart/form-data(axios 自动识别 FormData 并设置)。分片上传需手动将文件切片(Blob.slice),逐片上传并在后端合并。上传示例:const form = new FormData(); form.append('file', fileBlob); axios.post('/upload', form)。文件下载: 配置 responseType: 'blob' 获取二进制数据,通过 URL.createObjectURL(blob) 创建临时链接,触发 <a> 标签下载。大文件下载注意内存,可用流式处理(Node 环境)。进度监控: 上传用 onUploadProgress,下载用 onDownloadProgress,回调参数包含 loaded 和 total,计算百分比:Math.round(loaded / total * 100)。底层基于 XMLHttpRequest 的 progress 事件,Node 环境不支持。CSRF 防护: 配置 xsrfCookieName 和 xsrfHeaderName,axios 自动从 Cookie 读取 XSRF-Token 并写入请求头。后端需在登录时设置 Set-Cookie: XSRF-TOKEN=xxx; Path=/。实例封装: axios.create() 创建独立实例,拥有自己的拦截器、默认配置和适配器,适合多 API 服务的项目隔离配置。 追问: 分片上传如何实现断点续传?需要后端配合什么接口? onUploadProgress 在 Node 环境下为什么不生效?有替代方案吗? 大文件下载如何避免浏览器内存溢出? axios.create 创建的实例和全局 axios 对象的拦截器是共享的吗? XSRF-Token 的 Cookie 为什么不能设 HttpOnly?这和 XSS 风险如何权衡?
服务端阅读 05月29日 22:54

axios 和 fetch 有什么区别?什么时候该用 axios 而非 fetch?

axios 和 fetch 的核心区别在 错误处理、拦截器、请求取消、数据转换、兼容性 五个方面。错误处理: fetch 只有网络故障才 reject,HTTP 4xx/5xx 仍走 resolve,需手动检查 response.ok;axios 自动将 4xx/5xx 转为 reject,错误处理更符合直觉。拦截器: axios 内建请求/响应拦截器,统一添加 Token、处理错误码;fetch 无拦截器,需手动包装或用第三方库。请求取消: axios 支持 CancelToken 和 AbortController;fetch 只支持 AbortController。axios 的超时配置(timeout)是内建的,fetch 需自己用 AbortController + setTimeout 实现。数据转换: axios 自动 JSON 转换(请求时 stringify、响应时 parse);fetch 需手动调用 response.json()。axios 自动处理 URL 编码和 FormData。兼容性: fetch 是浏览器原生 API,无依赖;axios 约 13KB gzipped。fetch 在旧浏览器需 polyfill(如 whatwg-fetch)。选 axios 的场景: 需要拦截器、自动错误处理、超时控制、请求/响应转换、取消请求。选 fetch 的场景: 追求零依赖、简单请求、Service Worker 中使用、项目已在用 SWR/React Query 等上层库。 追问: fetch 的 credentials: 'include' 和 axios 的 withCredentials: true 行为是否一致? fetch 如何实现和 axios 拦截器类似的功能? 在 Service Worker 中为什么推荐用 fetch 而非 axios? axios 的响应拦截器能拿到原始的 Response 对象吗? React Query 或 SWR 底层用的是 axios 还是 fetch?能切换吗?
服务端阅读 05月29日 22:54

axios 性能优化有哪些技巧?如何减少冗余请求?

axios 性能优化围绕 请求去重、缓存、并发控制、体积优化 四个维度。请求去重: 对同一接口的并发请求做合并,避免重复发送。实现方式:在请求拦截器中用 URL+参数生成 key,维护一个 Map 记录正在进行的请求,相同 key 的请求复用同一个 Promise,响应后删除 key。也叫"请求锁"或"请求合并"。请求缓存: 对不常变的数据(配置信息、字典表)做本地缓存。在响应拦截器中按 URL+参数缓存响应,设置 TTL 过期。也可用 HTTP 缓存头(Cache-Control、ETag)配合浏览器缓存,axios 的 adapter 可实现自定义缓存适配器。并发控制: 使用 Promise.all 并发请求提升加载速度;对大量并发用并发池控制(如 p-limit),避免浏览器同域 6 连接限制导致的排队。批量接口优先用后端聚合 API,减少请求次数。体积优化: 开启 gzip 压缩(服务端配置);请求参数精简,只传必要字段;响应数据按需获取(分页、字段过滤);大文件上传用分片上传减少超时风险。 追问: 请求去重的 Map 在请求失败时如何清理?避免后续请求被阻塞? 自定义缓存 adapter 如何处理 POST 请求的缓存策略? 浏览器同域并发连接限制对 axios 有什么影响?如何绕过? 如何实现 axios 请求的优先级队列? 分片上传的断点续传如何在 axios 中实现?
服务端阅读 05月29日 22:54

axios 存在哪些安全风险?如何防范 XSS 和 CSRF 攻击?

axios 的安全风险集中在 CSRF、XSS、敏感数据泄露、SSRF 四个方面。CSRF 防护: axios 内置 CSRF 防护,通过 xsrfCookieName 和 xsrfHeaderName 配置自动从 Cookie 读取 Token 并附加到请求头。后端需设置 Set-Cookie: XSRF-TOKEN=xxx,前端配置 axios.defaults.xsrfCookieName = 'XSRF-TOKEN'。对于 SameSite Cookie 策略,建议后端设置 SameSite=Strict 或 Lax 作为双重保障。XSS 防护: axios 本身不执行 HTML,但返回数据若直接插入 DOM(如 v-html、dangerouslySetInnerHTML)会导致 XSS。必须对响应数据做转义,或使用 DOMPurify 净化。另外避免在 URL 参数中拼接用户输入,防止反射型 XSS。敏感数据泄露: Token 不要存 localStorage(XSS 可读取),优先存 HttpOnly Cookie;请求拦截器中不要把 Token 打印到日志;响应拦截器中敏感字段(密码、密钥)应在日志中脱敏。SSRF 防护: 服务端使用 axios 时,若 URL 来自用户输入,需校验目标地址,禁止请求内网 IP(127.0.0.1、10.x.x.x、192.168.x.x),使用白名单域名策略。 追问: axios 的 XSRF 防护机制在前后端分离架构下如何实现? SameSite Cookie 的 Strict 和 Lax 模式对 CSRF 防护有什么影响? HttpOnly Cookie 方案在跨域场景下如何配置 CORS? 如何对 axios 响应数据做自动化脱敏? SSRF 攻击中如何绕过 IP 黑名单?白名单方案怎么设计?
服务端阅读 05月29日 22:54

axios 代码怎么做单元测试?Mock 请求的常用方案有哪些?

测试 axios 代码的核心是 隔离网络请求,常用方案有三种:axios-mock-adapter、jest.mock + msw。axios-mock-adapter: 直接拦截 axios 实例的请求,按 URL 和方法注册 mock 响应。适合纯 axios 项目,API 直观。示例:mock.onGet('/api/user').reply(200, { name: 'test' })。可模拟超时、网络错误、指定状态码。缺点是绑定了 axios 实例,切换请求库需重写 mock。jest.mock('axios'): 直接 mock axios 模块,控制 axios.get/post 等方法的返回值。适合快速编写测试,jest.mock('axios') 后用 axios.get.mockResolvedValue() 设定返回。优点是零依赖,缺点是绕过了拦截器逻辑,无法测试中间件行为。MSW(Mock Service Worker): 在 Service Worker 层拦截请求,不依赖任何 HTTP 库。最接近真实网络行为,可共享给集成测试和 E2E。通过 handler 匹配请求并返回 mock 数据。推荐用于新项目。选型建议: 项目只用 axios → axios-mock-adapter;需要快速单元测试 → jest.mock;多请求库或需要更真实模拟 → MSW。 追问: jest.mock 和 jest.spyOn 在 mock axios 时有什么区别? 如何测试请求拦截器中的 Token 注入逻辑? MSW 的 Service Worker 在 Node 环境下如何工作? 如何模拟 axios 的网络超时和 5xx 错误场景? axios-mock-adapter 能否模拟请求进度(onUploadProgress)?
服务端阅读 05月29日 22:54

axios 底层是怎么实现的?核心架构和请求流程是怎样的?

axios 本质是 请求/响应拦截器管道 + 适配器模式,核心流程为:配置合并 → 请求拦截器 → 分发请求 → 响应拦截器 → 返回结果。适配器模式: axios 不直接发请求,而是通过 adapter 抽象层。浏览器环境用 xhr.js(基于 XMLHttpRequest),Node 环境用 http.js(基于 Node 的 http/https 模块)。通过 adapter 配置项可自定义适配器,这是 axios 跨平台的关键。拦截器机制: 维护两个链式数组 request interceptors 和 response interceptors,每个拦截器有 fulfilled 和 rejected 两个回调。请求时将配置、拦截器和 adapter 按 Promise 链顺序串联执行,形成 [req1 → req2 → ... → adapter → ... → res2 → res1] 的管道。配置合并策略: 三层配置合并——默认配置(defaults)→ 实例配置(instance.defaults)→ 请求配置(请求参数),通过 mergeConfig 按策略合并,headers 单独处理。请求流程: axios.request() 是统一入口,其他方法(get/post 等)最终都调用 request。内部创建 Promise 链,将拦截器成对插入链的两端,adapter 在链中间执行实际请求,支持取消(CancelToken)和超时控制。 追问: 拦截器的执行顺序是什么?请求拦截器和响应拦截器分别是正序还是逆序? 如何自定义 adapter 实现 Mock 数据或缓存层? CancelToken 基于什么原理实现的?为什么新增 AbortController 方案? mergeConfig 对不同类型的配置项(如 headers、transformRequest)采用了什么合并策略? axios 的 Promise 链如果中间某个拦截器抛异常,后续拦截器还能执行吗?
服务端阅读 05月29日 22:54

React Native 调试有哪些方法?各调试工具分别适用什么场景?

React Native 调试分 JS 层调试、原生层调试、性能分析 三个层面。JS 层调试: Chrome DevTools 是最基础的方式,通过 Ctrl+M 打开开发者菜单选择 Debug 打开 Chrome 调试。但 Chrome 调试运行在 Chrome V8 而非设备 JSC/Hermes 上,存在兼容差异。推荐使用 Flipper,它内置 React DevTools 和网络检查器,支持断点、Console、组件树检查,是官方推荐的调试平台。原生层调试: Android 用 Android Studio 的 Logcat 过滤 ReactNativeJNI 日志,可对原生模块设断点调试;iOS 用 Xcode 的 LLDB,在 RCTBridge 方法处打断点。性能分析: Perf Monitor(开发者菜单内)查看 FPS 和内存;Systrace 记录帧渲染时间线定位掉帧原因;Hermes 引擎自带 CPU Profiler 生成 Chrome Trace 格式文件。React DevTools Profiler 分析组件渲染耗时和频率。常用工具总结: Flipper(全能调试)、React DevTools(组件树)、Chrome DevTools(JS 断点)、Xcode/Android Studio(原生调试)、Systrace(性能分析)。 追问: Chrome 调试模式和 Hermes 引擎调试有什么区别? Flipper 在新架构下是否还适用?有什么替代方案? 如何对 React Native 的启动耗时进行量化分析? 生产环境如何收集 JS 异常和崩溃日志? Hermes 的 CPU Profiler 生成的 trace 文件如何分析?
服务端阅读 05月29日 22:54

React Native 性能优化怎么做?常见性能瓶颈如何排查和解决?

React Native 性能优化的核心是 减少 JS Bridge 通信、控制重渲染、优化列表滚动 三个方向。减少 Bridge 通信: Bridge 是异步串行的,高频调用会积压队列。将批量操作合并为一次原生调用,使用 Native Modules 批量传递数据而非逐条传递。新架构 Fabric 取代了异步 Bridge,实现同步通信。控制重渲染: 使用 React.memo 包裹子组件避免不必要的 re-render;用 useMemo 缓存计算结果、useCallback 缓存回调函数;列表项拆分为独立组件并 memo 化。避免在 render 中创建内联对象和函数。优化列表: FlatList 替代 ScrollView 渲染长列表,设置 keyExtractor、getItemLayout 提升性能;windowSize 控制渲染窗口大小;removeClippedSubviews 回收不可见视图。VirtualizedList 是 FlatList 的底层,可做更细粒度控制。其他关键点: 图片使用缓存库(如 react-native-fast-image);动画用 useNativeDriver 驱动跑在原生线程;避免在主线程做 JSON 解析等耗时操作;Profiling 工具用 Flipper 或 Systrace 定位瓶颈。 追问: React.memo 的浅比较在什么场景下会失效?如何自定义比较逻辑? FlatList 的 windowSize 参数设为多少合适?过小会有什么副作用? useNativeDriver 为什么不能驱动布局属性(如 height)的动画? 新架构 Fabric 和 TurboModules 相比旧 Bridge 的性能提升体现在哪里? 如何用 Systrace 定位 JS 线程和原生线程的耗时瓶颈?
服务端阅读 05月29日 22:54

Android四大组件分别是什么?各自承担什么职责?

Android四大组件是 Activity、Service、BroadcastReceiver、ContentProvider,它们是构成 Android 应用的基石,各自负责不同的职责边界。Activity 负责用户界面的展示与交互,一个屏幕对应一个 Activity,通过 Intent 实现页面跳转和数据传递,生命周期由系统回调管理(onCreate → onResume → onPause → onDestroy)。Service 在后台执行长时间运行的操作,不提供界面。分为 Started Service(startService 启动,与调用者无关)和 Bound Service(bindService 绑定,允许通信)。注意 Service 仍运行在主线程,耗时操作需开子线程。BroadcastReceiver 监听并响应系统或应用发出的广播消息,如开机启动、网络变化、电量改变。分静态注册(AndroidManifest 声明,应用未启动也可接收)和动态注册(代码注册,跟随组件生命周期)。ContentProvider 管理应用间数据共享,提供标准 CRUD 接口,通过 URI 定位数据。系统联系人、短信等均通过 ContentProvider 暴露。 追问: Activity 的四种启动模式分别适用于什么场景? Service 和 IntentService 的区别是什么?IntentService 为什么已废弃? 静态注册广播在 Android 8.0 后有哪些限制?如何适配? ContentProvider 的 URI 格式是怎样的?如何自定义 Authority? 四大组件中哪些可以在 Manifest 中声明多个实例?