2022-09-29其他00

二进制

通过 accept 限制上传文件类型

在日常工作中,文件上传是一个很常见的功能。在某些情况下,我们希望能限制文件上传的类型,比如限制只能上传 PNG 格式的图片。针对这个问题,我们会想到通过 input 元素的 accept 属性来限制上传的文件类型:

<input type="file" id="inputFile" accept="image/png" />

这种方案虽然可以满足大多数场景,但如果用户把 JPEG 格式的图片后缀名更改为 .png 的话,就可以成功突破这个限制。因为通过 文件后缀名或文件的 MIME 类型 并不能识别出正确的文件类型。我们可以通过读取文件的二进制数据来识别正确的文件类型。

如何通过二进制查看图片的类型

计算机并不是通过图片的后缀名来区分不同的图片类型,而是通过 Magic Number 来区分。 对于某一些类型的文件,起始的几个字节内容都是固定的,根据这几个字节的内容就可以判断文件的类型。

常见图片类型对应的 Magic Number 如下表所示:

文件类型文件后缀魔数
JPEGjpg/jpeg0xFF D8 FF
PNGpng0x89 50 4E 47 0D 0A 1A 0A
GIFgif0x47 49 46 38(GIF8)
BMPbmp0x42 4D
2022-09-29其他00

优雅代码

If 语句

bad

if (value === "duck" || value === "dog" || value === "cat") {
  // ...
}

good

const options = ["duck", "dog", "cat"];
if (options.includes(value)) {
  // ...
}

提前退出机制

function handleEvent(event) {
  if (event) {
    const target = event.target;
    if (target) {
      // ...
    }
  }
}

使用提前退出,减少嵌套

function handleEvent(event) {
  if (!event || !event.target) {
    return;
  }
  // ...
}
2022-09-29质量保障00

前端错误的分类

  • 资源加载错误
  • 代码运行错误

错误的捕获方式

即时运行错误的捕获方式

  • try - catch
  • window.onerror

资源加载错误

  • object.onerror
    • image 标签、script 标签上都可以加 onerror 事件
    • 资源加载错误不会冒泡,但会捕获
  • performance.getEntries()
    • 获取所有已经加载资源的获取时长
  • window 对象上通过事件捕获 Error 事件

注: addEventLitener('事件类型', function(e){ /回调函数/ },捕获 true 或冒泡 false )

一般情况下错误监控都是在捕获的阶段进行。

跨域的 JS 运行错误

因为了,只知道错误,但是无法定位错误信息 解决方法:

  1. 客户端,在 script 标签上增加 crossorigin 属性
  2. 服务端,设置 JS 资源响应头 Access-Control-Allow-Origin: *

上报错误信息

  1. 采用 Ajax 通信上报
  2. 利用 image 对象的 src 属性上报
2022-09-29质量保障00

前端监控

前端监控包括行为监控、异常监控、性能监控。

前端产生异常的原因主要分 5 类:

  • 逻辑错误
    • 业务逻辑判断条件错误
    • 事件绑定顺序错误
    • 调用栈时序错误
    • 错误的操作 js 对象
  • 数据类型错误
    • 将 null 视作对象读取 property
    • 将 undefined 视作数组进行遍历
    • 将字符串形式的数字直接用于加运算
    • 函数参数未传
  • 语法句法错误
  • 网络错误
    • 请求过慢
    • 服务端未返回数据但仍 200,前端按正常进行数据遍历
    • 提交数据时网络中断
    • 服务端 500 错误时前端未做任何错误处理
  • 系统错误
    • 内存不够用
    • 磁盘塞满
    • 壳不支持 API
    • 不兼容
2022-09-29质量保障00

Istanbul 测试覆盖率的实现原理

Istanbul (伊斯坦布尔)是一个基于 JavaScript 的测试覆盖率统计工具,目前绝大多数测试框架比如 jest mocha 等都是使用 Istanbul 来统计覆盖率的。

测试覆盖率的四个维度

  • Statements
    • 语句覆盖率,所有语句的执行率;
  • Branches
    • 分支覆盖率,所有代码分支如 if、三目运算的执行率;
  • Functions
    • 函数覆盖率,所有函数的被调用率;
  • Lines
    • 行覆盖率,所有有效代码行的执行率,和语句类似,但是计算方式略有差别;

Istanbul 的使用

istanbul 最新的版本为: nyc,官方站点为:https://istanbul.js.org,github: https://github.com/istanbuljs/nyc。下面将简称 Istanbul 为 nyc

传统的前端项目测试,假设使用 mocha 测试,我们会执行以下的测试用例:

`mocha test/suite/\*_/_.spec.js`

接着开发者安装 nyc npm 类库(npm install nyc -D),然后加个 nyc 前缀就会自动 完成运行时的覆盖统计与最终结果展现;

// nyc 无参数的默认用法
nyc mocha test/suite/**/\*.spec.js
// nyc 携带参数:html 格式
nyc --reporter=html mocha test/suite/**/\*.spec.js
// 也可以通过项目根目录增加配置文件(如:nyc.config.js)的形式,然后执行上面的命令
module.exports = {
reporter: ['html']
}

该命令执行时,会依次完成以下几件事:

  1. 将项目 src 源码目录中的 JS 文件做转换并缓存起来;

  2. 接着将后面的 mocha 参数放到子进程(child_process)执行,即:调用 mocha 执行测试用例;

  3. 测试用例中所测试的 src 源码文件实际是上面的缓存文件,期间完成的语句与分支执行的统计,记录在 JS 内存的某个变量中;

  4. 子进程的测试用例执行结束之后,将统计数据发送给 nyc 命令所在线程并保存到文件,默认目录名为:.nyc_output,它记录了本次测试的代码覆盖最完整的数据;

  5. nyc 线程内部调用 report 方法,完成从原始数据到可读性良好的内容转换;它会将 .nyc_output 目录中的数据读取出来,并使用 html 格式 进行转换,并默认生成在目录 coverage 下;