面灵AI→

拼多多前端一面:上传成功率、性能优化与 Promise 手撕

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 请做一下自我介绍。
  2. 上传成功率是怎么做的?
  3. 性能优化是怎么做的?
  4. 拖拽排序算法怎么实现?
  5. 手撕:结合 Promise 实现失败重试与超时处理。
  6. 手撕:扁平化数组,并根据传入数字实现可控次数的扁平化。
  7. 用 CSS 画图形,说说实现思路。
  8. 判断事件循环的输出顺序。

《参考解析》

上传成功率:先定义指标——成功上传数除以发起上传数,再按文件大小、网络类型、端类型拆分,避免大文件失败被小文件稀释。实现上用分片上传,每片独立重试并记录进度;文件 hash 做秒传和断点续传,弱网下降低并发、缩短超时;超过重试上限就给出可恢复的失败态。前端还要把网络、超时、服务端拒绝等原因带回埋点。

性能优化:先测量再改,用 LCP、INP、CLS 和长任务定位瓶颈。加载侧做路由级代码分割、图片压缩与响应式尺寸、静态资源长缓存;渲染侧减少首屏依赖、列表虚拟化、避免不必要重渲染;运行时把大计算拆片或放进 Worker。每项优化都要有前后指标对比。

拖拽排序:核心是「指针位置到目标索引,再移动数组」。监听 pointerdown、pointermove、pointerup,拖拽中用 transform 跟随指针,用占位元素腾出落点,根据指针中心与元素中点的关系算目标索引;移动端还要处理滚动容器自动滚边。高频更新用 requestAnimationFrame 节流,拖拽结束只提交一次顺序。

Promise 失败重试与超时:把单次请求包成 runOnce,用 Promise.race([request, timeoutPromise]) 让超时先 reject,并在 finally 里 clearTimeout 防止定时器泄漏。外层循环维护 attempt,捕获错误后判断是否可重试,并给超时错误打标记;重试间隔用指数退避加随机抖动,到上限抛最后一次错误。每次重试都要新建超时 Promise,不能复用已 reject 的那个。

可控深度扁平化:递归写法最直观:depth 小于等于 0 时返回原数组的浅拷贝,否则遍历元素,是数组就递归 depth - 1 并展开,不是就 push。不想递归可以用显式栈存值与剩余深度,避免深层嵌套爆栈。原生 Array.prototype.flat(depth) 默认只降一层且会跳过空位。