【有赞社招】电话面+技术面+hr面

通过朋友内推有赞,经过电话面+技术面+hr面的完整面试流程,最终没有拿到offer,这儿给大家分享一下面试经验。


电话面试

有赞的面试流程是内推流程过了后,会有电话面试的人跟你约你方便的时间。

以下是我在电话面试中遇到的一些问题:

电话面试还是比较喜欢基础好一些的候选人,跟我想的差不多,就结束了本次电话面试,整体过程还是挺好的。

电话面试2-3天左右很快就有了答复,告诉我通过了,约了复试,电话面试的小哥很负责,陆陆续续打了2个电话反复沟通。

技术面(现场面试)

  • 你做的非覆盖式发布是指什么?

这个问题我回答了好久,一边回忆一边说,因为当时配置好之后就全权交给运维去做了,后期维护的一些改变运维方面我没有及时去看,一直在看产出的报告,导致这个问题我答得磕磕巴巴的,面试之前千万千万要回顾并熟知每一个细节,否则就是给自己挖坑,下面是我面试时+面试后重新梳理的答案。

首先简单介绍了覆盖发布和非覆盖发布的区别

  • 覆盖发布:前端项目打包后每次产生相同的文件名,发布至服务器时,同名文件直接替换,新文件添加。
  • 非覆盖式发布:采用更新文件名的形式,比如采用webpack的[id].[chunkhash].js的形式,这样更新文件后,新文件不会影响旧文件的存在。

覆盖式发布的缺点:

  • 先更新页面再更新静态资源
    新页面里加载旧的资源,页面和资源对应不上,会有页面混乱,还有执行会报错。
  • 先更新静态资源再更新页面
    在静态资源更新完成,页面没有被更新过程中,有缓存的用户是正常的。这个时候读本地的缓存,但是如果没有缓存的用户会怎样?依然是会页面混乱和执行错误,因为在旧的页面加载新资源

无论如何,覆盖式发布都是能被用户感知到的,所以部分公司的发布是晚上上线。其中如果使用vue-cli直接生成webpack配置打包的话,直接发布dist文件夹下资源就会产生这种特殊的替换问题,因为在build.js文件中存在这么一行代码,初衷应该是防止dist文件夹越来越大,但是rimraf模块会递归删除目录所有文件,没有详细了解过vue-cli生成编译环境的人,就默认的采用了这种旧资源删除新资源生成。

// build.js
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
    ...
})

  • 你提到的nginx的静态文件缓存策略是什么?
  1. 静态资源html不使用缓存,每次加载均从服务器中拉取最新的html文件
  2. 静态资源js/css/图片资源,采取强缓存策略,这个时间可以尽可能的长一些,因为是非覆盖式发布,所以如果html中加载资源URI更新,那么资源也会统一的更新

然后发布的时候先将除html文件移动至发布路径,同名文件默认跳过,新生成的文件会产生新的hash,新旧文件不会冲突,共存在发布路径。

html文件的更新当时做了两种方案

  1. html完全由前端管理,前端发布的时候会有html文件,webpack打包时自动在html里写文件名;
  2. html由后端管理(服务器渲染),前端只负责发布js、css等资源文件。在前端发布之后,后端修改版本号再发布;

因为node经验匮乏,当时第二种方案用了python写了一个服务,配置manifest.[chunkhash].jsvendor.[chunkhash].js,如果项目中存在首页骨架屏,那么还需要替换html文件body中的内容,用户服务进来后直接加载这个渲染后的页面。

  • cdn 答不好什么就会一直往下问,面试如果发现状态不对的话,尽量别被牵着鼻子走吧,这个问题我中间说错了一个环节,导致有点崩,我当时说了我当时部署的项目一部分文件是不走cdn的,可能耐心值达到红色线了,这个是答得是有歧义的。

分场景的话:

  1. 服务器渲染,那么除html文件均分发一份在cdn上,保证服务器负载
  2. 频繁更新的配置,比如某些项目是插槽模式嵌入功能的,就需要后端接口生成相应的配置文件,以接口的形式发给前端进行解析。

cdn的配置经验我比较少,公司的业务场景暂时没有提供cdn功能,所有的图片走的是七牛云的cdn,而服务器的css/js文件方面的cdn部署,没有相关的使用经验,面试回到家后一直在找相关的解决方案,如果你有比较好的科普性质的博文,欢迎在评论区留言。

  • 项目经验,个人角色

可能前面的问题答得有些失误,为了缓和气氛问了这个问题。因为我之前一直做公司的web前端负责人,所以这个问题聊的比较迅速。我之前的公司是刚开始是没有前端的,我算是半路出家,公司从30人发展到500人,前端团队由2个人发展到接近10个人。然后说了下我主要负责的项目,以及一些团队协作,风险评估,需求评审,代码质量保证的一些事情,可能我做的工作有点low,TL的表情反馈有些平静。

  • gzip编码协议

这个看过一些,大概就是和缓存策略一样,需要在服务器进行配置,同时需要浏览器的支持。

http {
    ...
    gzip on; // 开启gzip
    gzip_min_length 1k; // 最小1k的文件才使用gzip
    gzip_buffers 4 8k; // 代表以8k为单位,按照原始数据大小以8k为单位的4倍申请内存
    gzip_comp_level 5; // 1 压缩比最小处理速度最快,9 压缩比最大但处理最慢(传输快但比较消耗cpu)
    gzip_types application/javascript text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; // 支持的文件类型
    gzip_disable "MSIE [1-6]\."; // IE6一下 Gzip支持的不好,故不实用gzip
    ...
}

服务器配置之后,会在浏览器请求接口后的response header的Content-Encoding字段看到gzip。

客户端请求数据时,请求头中有个Accept-Encoding声明浏览器支持的压缩方式,当客户端请求到服务端的时候,服务器解析请求头,如果客户端支持gzip压缩,响应时对请求的资源进行压缩并返回给客户端,浏览器按照自己的方式解析。

然后拓展问了下,如果传输的数据希望后端压缩,但是算法没有声明如何启用后端算法。我就模拟了下这个流程,客户端利用header头部的自定义字段将可以容忍的压缩算法告诉服务端,服务端配置允许发送这个自定义header,逐个匹配服务器上当前的算法,匹配到则发送成功结果,无法匹配则告知客服端数据无法进行压缩,等待接下来的操作。

  • 高精度计时器

算是一个解决方案的问题,面试官列举了一个有赞整点抢单的业务场景,如何同步所有客户端的时间。由于setTimeout类似的计时器无法高精度还原时间,我提出的想法是利用socket保持和服务器的长链接,利用推送的模式,定期给客户端发送当前服务器时间作为校验基准,但是由于HTTP传输的时间无法保证,所以也只能尽可能的同步两端的时间。

面试官又问了这个服务器推送的频率你认为大概需要多少,因为没有相关业务经验,只能按照逻辑推理,这个我的描述是当前服务器时间 = 服务器系统返回时间 + 网络传输时间 + 前端渲染时间 + 校准常量(可选),所以这个推送的频率采用变频的思路,就是离活动时间有一段时间,那么推送频率大概1分钟2次左右,马上快开始就需要频繁推送了,socket性能问题需要通过不断的矫正才能达到最好的效果,但是如果想100%实现高级度的计时器,以我目前的知识面看,还是存在很多问题的。

其实这个问题我在C++中就实践过,如果想测试超高级度的定时器,需要中间没有阻塞线程或者进程,以及防止计算机优先级较高的任务中断,这个知识涉及到操作系统的好多知识,大概就说到这。

对于这个问题我还是很感兴趣的,因为我面试后发现很多这种活动都有这个时间误差的问题,或大或小。如果你有过相关的业务场景,欢迎留言区分享你的思路。

  • 提取最长有效数字

技术面试过程的最后感觉自己可能没戏了,没想到还被问了一个现场编码的题目,大致题意如下:
Input:

  1. '1024word'
  2. ' -1024word'
  3. 'word1024'
  4. '10word24'

Output:

  1. 1024
  2. -1024
  3. 0
  4. 10

程序大概写了不到5分钟吧,印象不是太深刻了,代码写的有点多。

function parseInt (value{
    // 输入值校验合法性
    if (!value) { return 0; }
    // 本需求对于空格需要剔除
    let temp = value.toString().trim();
    // 拦截全空字符串问题
    if (temp.length === 0) {
        return 0;
    }
    // 收集符号位
    let result = temp[0] === '+' || temp[0] === '-' ? temp[0] : '';
    // 设置开始索引
    let i = result.length > 0 ? 1 : 0;
    // 遍历,此处使用for循环为了方便中断遍历减少时间复杂度
    for (;i < temp.length; i++) {
        if (temp[i] >= '0' && temp[i] <= '9') {
            result += temp[i]
        } else {
            break;
        }
    }
    // [防爬虫标识-掘金-沙海听雨]
    // 判断存在result为符号位造成Number('+')输出NaN问题
    return result && (result === '+' || result === '-') ? 0 : Number(result)
}

问了能不能换种方法实现,我想了一下,说正则提取可以做到,但是当时就给了10分钟不到的时间,就没再继续了,其实是之前的问题把思路打乱了,一直在回忆之前没答好的问题。

下面是正则表达式的实现方法

// 方法一
function parseInt (val) {
  if (typeof val !== 'string') { return 0; }
  let match = val.toString().trim().match(/[+|-]{0,1}[0-9]*/g)[0];
  if (!match) {
    return 0;
  }
  return Number(match)
}

// 方法二
function parseInt (val) {
  if (!val || typeof val !== 'string') { return 0; }
  return +val.toString().replace(/^\s*([-+]?\d+)?.*$/, ($0$1) => $1 || 0)
}

这个表达是里面用到的概念有点多,一直没有时间更新,其中几个关键点,在此处分析一下。

`^`以什么为开始  
`\s`匹配任意的空白符  
`*`只匹配出现 0 次及以上 \* 前的字符  
`()`分组 `[]`匹配方括号内的任意字符  
`?`之前字符可选  
`\d`匹配数字  
`+`只匹配出现 1 次及以上 + 前的字符`.`匹配任意字符除了换行符和回车符(贪婪匹配)
  • 最后聊了一会骨架屏

本来感觉结束了,整体单方面被虐,没想到TL说等一下,让hr来找我聊聊,有点意外,等了大概10分钟吧,hr小姐姐就过来进行人事面。


hr面

这个面试流程我就基本精炼一下:

  • 询问了公司经历,就是为什么入职为什么离职
  • 由于我做技术比较杂,城市也比较多,聊了好久一阵子,可能是怕我简历有水分吧

我大学时期做ASP.Net,大学毕业第一份工作是C/C++嵌入式,后来又做了近一年的Django开发,最近两年才开始专一从事前端,所以这个聊的比较多,我觉得一个人能快速适应各种语言,算是一个优势吧,能侧面反应计算机基础,但另一方面广度过于宽会导致深度不够,这个我开始逐渐调整,由于掌握的语言比较多,所以上手很多技术还是很快的。

  • 询问了个人发展规划

我的期许就是待遇上匹配的上时间成本,最重要的是想在一家规模比较大的企业做的久一些,沉淀一下业务能力和技术视野,大公司遇到的场景、并发、极端交互还是很令我向往的。

  • 聊了下期许的薪资
    我大概说了个数字,反正很诚心吧,有很大谈的余地,因为真的想跳出目前一直在小公司怪圈。

  • 聊了整个面试流程感觉如何

  • 说了合适的话会打电话沟通,不合适的话会发邮件通知原因


自我总结

hr面试让我心里有些释怀,一扫之前技术面的紧张感,出门的时候如释重负吧,算是一个小阶段的结束,为了这个面试大概准备了1个多月,后来可能太紧张又是杭州梅雨季,回到家有些低烧,都是小插曲了。

最后的最后,等了大概一周多吧,还是没有消息,我对面试还是特别有诚意的,想等到结果再进行下一步,就问了内推我的朋友,得知面试被淘汰了,没接到正式婉拒通知有点小意外,可能各种原因,当个经历继续前行吧。

经历了完整的大企业面试算是对自己的一个自我认知的过程,虽然中间经历还是比较曲折的,但是算是成长吧,找工作还是有些吃力的,但是还是期待大公司的工作机会吧。

面试官点评

这位同学一共经历了2轮技术面和一轮HR面。

电话面的题都特别基础,相信大家只要好好准备下,问题都不大,这位同学也回答的比较好,进入了第二轮技术面。

但这位同学的第二轮技术面暴露的问题很多,特别是前端的代码发布方式这个问题,本来是很简单的一个题目,却花了大量的时间去和面试官沟通,而且面试官深入问细节时,答的又很糟糕。

建议大家在面试中遇到不熟悉的知识点时,千万不要磕磕绊绊的回答,直接告诉面试官自己知道哪些即可,不要浪费大家的时间。

最后

“前端面试题宝典”经历接近一年的迭代打磨,目前已经提供了小程序刷题、PC端访问(https://fe.ecool.fun/)。

截至2022年3月24日,已经录入前端常见面试题800+,想刷前端面试题的小伙伴千万不要错过。

我们在近期推出了简历指导、模拟面试等增值服务,有想了解的小伙伴们可以添加小助手微信(interview-fe)进行咨询哦~

面经作者:沙海听雨面经来源:https://juejin.cn/post/6844903890735857677