记帮主成功的字节二面

假如您也和我一样,在准备春招。欢迎加我微信shunwuyu,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!

前言

今天是元宵,祝大家元宵快乐,吃的甜甜蜜蜜,过的热热闹闹。记帮主成功的字节面试 - 掘金 (juejin.cn)记住了IT帮帮主成功的字节一面,还在家里被百度一面吓坏的我,梦里惊魂又坐起,给大家继续记录帮主的字节二面面经。如烟也约到了百度和小米的面试, 帮主每天电话陪伴模拟面试,金三银四工作爱情双丰收...

二面面试题

自我介绍

大家可以查看面试:百度一面,吓尿了 - 掘金 (juejin.cn),里面介绍了敖丙大佬自我介绍公式:我是谁+从哪里来+我做过什么+有什么成绩+为什么能胜任。

帮主说他也基本是这个套路,会刻意把对代码的热情、学习方式(引出怎么学习这道热题,早已准备好)、AI的兴趣(引出对LLM的理解,看待未来的方式)

根据项目中滚动到底部

帮助在项目中,首页列表使用到了滚动到底部加载更多功能。业务代码耦合在组件里,比如事件监听,page参数watch执行请求, 节流等。面试官问可不可以优化一下?

首先,滚动到底部加载更多功能确实挺复杂的。帮主在介绍项目的时候,也把它作为了项目的难点来表达。一面面试官没发难,二面这一上来就开火了。 大家在面大厂的时候,确实要提前准备好自己的项目亮点和难点。如果除了基本的全家桶、组件化外, 没啥细节,定是过不了的,因为面试官连刁难我们的点都找不到。下次我再开篇, 单独讲项目优化和整理,欢迎大家关注或加我微信shunwuyu, 一起为春招大厂努力。

说实话,这个问题不好回答。写项目的时候赶工,能写出来就不错了。vue 好学, 边看文档边就把代码写起来了。遇到滚动加载更多的时候,这个难点折腾了小一天才搞定。既然面试官把这个点捅了出来,面试时的求生欲望让帮主疯狂思考有没有大致思路?帮主项目功底深厚,半分钟后聊出来他会怎么优化这个功能

封装复用

滚动到底部加载更多是大部分List组件(项目没有使用第三方UI组件)都需要的功能,事件监听、节流、page、请求、动态效果等都大致相同,封装好就不用每次重新写一堆屎山代码了,遵守DRY原则。

hooks

hooks 函数是Vue3的重大特性,在一面中,帮主也介绍到了自己使用到的一些hooks函数。用函数做封装,hooks 函数除了封装外,还可以将状态、生命周期、事件监听和移除等都封装到它的内部。因为之前项目里没有写过这么复杂的自定义hooks功能,帮主就大概的把思路讲了一下,再细讲容易出马脚。差不多就收,面试官还满意,双方沉默了几秒...

Better Scroll

最后, 帮主打破沉默,绝杀....

记得好像之前接触过黄轶老师的Better Scroll, 处理滚动,滚动加载事件如丝般顺滑,如果自己在公司项目中,应该会使用这个组件,或公司组件库中的相应组件。

我也打开黄轶老师的better-scroll/packages at dev · ustbhuangyi/better-scroll (github.com)项目,将自己项目的滚动列表换成了Better Scroll.

这样,下次介绍项目的时候就有亮点了,还可以细讲自己从耦合代码到封装,再到采用业内组件的思考和解决过程。

封装请求拦截

一面, 帮主介绍了JWT。二面面试官继续刁难,在axios请求拦截添加Authorization字段,要求手写实现用fetch 代替axios封装请求拦截器功能。

果然大厂考的都比较底层,对实习生代码动手能力要求太高了。

首先, 面试官想看我们对JWT的理解程度,因为cookie的安全还有性能问题,我们选择JWT 方案,每次在HTTP请求头中使用Authorization字段带上token(服务器端返回token后存在localStorage里), 就完成了前端部分功能。

其次,查看我们理解http, 手写promise(fetch就是promise实例),不依赖axios API , 自己完成功能的能力。

js 复制代码
// 假设你有一个获取JWT Token的方法 
function getJwtToken() { 
    // 在这里获取实际的token,例如从localStorage或cookie中读取 
    return localStorage.getItem('jwtToken'); 
} 
// 封装fetch方法,使其自动添加JWT Token到Authorization header 
function fetchWithAuth(url, options = {}) { 
    const init = { 
        ...options, 
        headers: { 
            ...(options.headers || {}), 
        Authorization: getJwtToken() ? `Bearer ${getJwtToken()}` : '', 
        }, 
    }; 
    return fetch(url, init) 
        .then(async (response) => { 
            if (!response.ok) { 
                        // 可以根据需要处理错误状态码,比如401未授权时刷新token并重试等 
            if (response.status === 401 ) { 
               ....
            } else { 
               ....
            } 
        }
        return response.json(); // 如果预期响应是JSON格式的话 
        }) 
        .catch((error) => { 
            console.error('Error fetching data:', error); 
            throw error; });
    } 
    // 使用封装后的fetch方法发起请求 
    fetchWithAuth('/api/protected-resource') 
        .then(data => console.log(data)) 
        .catch(error => console.error('Error:', error));

果然,这道题后,面试官让我做道promise的题....

没有扎实的代码能力, 字节确实不好面啊。

promise 功能函数

题目是这样的:实现一个函数, 传入一个promise数组,且每一项都是一个函数,函数的返回值是promise实例 。 逐个调用函数,拿到每次的结果再调用下一个,最后拿到操作结果,并支持promise链式调用

  • 函数要支持promise链式调用 简单,只需要返回promise实例就好

  • 逐个调用 promise的 all、react 等是并行执行。串行执行,并且持续执行我想到用reduce来做。

js 复制代码
function serialPromiseExecution(promiseArray) {
    return promiseArray.reduce((chain, currentPromiseFn) => {
      // 确保 currentPromiseFn 是一个返回 Promise 的函数
      if (typeof currentPromiseFn !== 'function') {
        throw new Error('All elements in the array must be functions that return a Promise');
      }
  
      // 使用上一个 Promise 的结果作为下一个 Promise 的输入(如果需要的话)
      return chain.then((previousResult) => 
        currentPromiseFn(previousResult)
          .catch((error) => { // 捕获并传播错误,保持整个链的稳定性
            throw error;
          })
      );
    }, Promise.resolve()); // 初始化为 resolved Promise,初始值为空
  }
  

这段代码有几个地方提醒下各位看官:

设计reduce支持promise 串行

  • 首先我们要理解reduce参数的意义。
js 复制代码
promiseArray.reduce((chain, currentPromiseFn) => {
}, Promise.resolve())

chain 是之前的处理, currentPromiseFn为当前项, Promise.resolve()为初始值。

  • 串联执行的实现
javascript 复制代码
return chain.then((previousResult) => 
...

初始值为 Promise.resolve(), 并且数组每项函数的运行结果都是promise实例(类型焚检测)chain.then 在promise A+规范中它的返回也是promise, 所以实现了reduce的promise 异步串式运行。

  • 上次的结果会作为下次运行的输入
scss 复制代码
 currentPromiseFn(previousResult)
  • 测试用例
js 复制代码
    const promises = [
    () => Promise.resolve(1),
    (value) => {
        return new Promise((resolve,reject) => {
            setTimeout(() => {
                resolve(value + 1)
            }, 2000)
        })
    },
    // (value) => Promise.resolve(value + 1),
    (value) => Promise.resolve(value + 2),
  ];
  • 结果
js 复制代码
serialPromiseExecution(promises)
    .then(finalResult => console.log(finalResult)) // 输出:4
    .catch(err => console.error('Error in the promise chain:', err));

reduce 的最后结果依然是 chain.then 所以可以thenable

总结

到这里, 学院IT帮帮主的二面,也在他扎实的编程能力下,用时一个多小时,征服了面试官。第二天,帮主就顺利拿下了offer, 开启了打麻将,过肥年模式。帮主还是太低调了,拿下全国最好的互联网公司,怎么找也得安排下相亲啊,同意的点赞。

帮主的字节面试让我收藏以下几点:

  • 时机取巧

年前就大量面试,积累面试经验,并试图拿下大厂虽少量但较急的部门实习offer。大的招聘是在金三银四,但是大厂有些部门在年前发展势头就凸显了,比如AI、新能源。这样的部门会在年前就发offer, 年后直接开工, 等不了春招的流程...

如果是低年级同学, 一定收藏我的这篇建议, 早点行动。

  • 扎实的编程能力

春招中的笔试加面试,这种流程会难很多。帮主的这次面试, 反映出字节该部门(为保密,不给出部门)急于招聘,也不在春招流程中,直接面试,这就是过年面大厂的优势。但是考察确实很有深度。两次面试都是中高难度编程、场景题狂轰滥炸,不是高手绝对搞不定。我从这份面试题里,明白了大厂对编程题的要求。再准备下算法相关,也去面。知道大厂要求,只要实力到位,准备充分,不是字节,就是百度....

参考资料

滚动加载更多

相关推荐
10年前端老司机1 小时前
什么!纯前端也能识别图片中的文案、还支持100多个国家的语言
前端·javascript·vue.js
摸鱼仙人~1 小时前
React 性能优化实战指南:从理论到实践的完整攻略
前端·react.js·性能优化
程序员阿超的博客2 小时前
React动态渲染:如何用map循环渲染一个列表(List)
前端·react.js·前端框架
magic 2452 小时前
模拟 AJAX 提交 form 表单及请求头设置详解
前端·javascript·ajax
小小小小宇7 小时前
前端 Service Worker
前端
只喜欢赚钱的棉花没有糖7 小时前
http的缓存问题
前端·javascript·http
小小小小宇8 小时前
请求竞态问题统一封装
前端
loriloy8 小时前
前端资源帖
前端
源码超级联盟8 小时前
display的block和inline-block有什么区别
前端
GISer_Jing8 小时前
前端构建工具(Webpack\Vite\esbuild\Rspack)拆包能力深度解析
前端·webpack·node.js