前端如何做好防御性编程(React)

起源

想写一下关于前端防御性编程的内容,这个内容好像在前端并没有提及特别多。

但是从个人角度来看,这个应该得到重视,但是这些往往是在开发中的细节,开发中很容易忽视掉。同时因为 JavaScript 语言的原因,缺失了传统面向对象的编译期,这些问题就更不容易发现了。

我觉得关于前端防御性编程,应该可以做成一个规范,现在这个事情多数时候是 Lint 工具帮我们做的,或者说是一些关于应用健壮性的思考,后续如果有机会想思考一下规范的事情。

前言

这篇文章想通过个人视角,从 React 出发,来谈谈开发过程中,需要注意的一些小点,管中窥豹。

熟悉流程

我们先从页面渲染,或者说在提前一些,从输入 URL 开始说。

  1. 输入 URL ,向服务器请求资源。
  2. 加载请求到的资源,渲染页面。
  3. 进入主页面,进行交互。

输入URL请求资源

看起来这个地方没什么好说的(也确实没啥好说的),就是简单的输入 URL 然后浏览器去解析,似乎并没有什么前端可以做的。

前端一般做好 404 页面即可,选择提示输入错误或者直接重定向到主页。

<Route path="*">
		<NoMatch />
</Route>

加载资源、渲染页面

这个地方也看似没有什么好做的,但其实不然,考虑的地方还是有些的。

  • 缓存

比较重要的一个点在于缓存,我们是否采用本地缓存来加载,这个点需要持续关注一下。包括但不限于缓存策略、过期时间。

  • 无网络(弱网)

无网络的情况下,策略是什么。以及弱网情况下,策略是什么,等待加载 or 交互提示。

这个地方涉及的挺广泛的,PC端、移动端策略都不太一样。如果是在移动端的策略上,如果要提高用户体验,弱网情况下,也应该加载本地组件(离线包)。有一些最基础的交互,并应该给出提示。

页面交互

页面交互其实也差不多,在处理大型输入输出、网络请求的时候,是否有完好的组件 Loading 状态,是否有比较完备的提示内容。

深入代码

1. 无网络提示(弱网)

这个地方策略不尽相同,全局鉴权提示网络不畅通、弹窗提示并跳转至某个页面等等。

我综合了团队中一些人的意见,意见比较一致的是全局鉴权提示。

我们可以对所有 API 进行请求拦截,如果请求网络错误,直接通过 errorMessage 或是一些提示组件进行提示。

export const request: RequestConfig = {
  credentials: 'include',
  errorConfig: {
    adaptor: (resData) => {
      // 全局adapter,或者通过拦截器
    },
  },
};

2. 组件初始(初始化、赋值)

这其实是一个比较难讲的事情,初始化的时候,该传哪些值?哪些值可选,哪些不可选?这些其实是一个编码时候的提示,这个使用 TypeScript 就可以。

export default (props: {
  // 用于页面刷新的回调
  pageRefresh?: () => void;
  // 用于判定范围,请求的范围参数(不传默认为范围一)
  inventoryScopeNo?: string;
  // 用于判断范围下的是哪个排放范围
  categoryNo?: string;
}) => {
  return 
  // 省略了组件
}

但是这还不够,除了编码提示,我们也不能完完全全把这个问题交给 TypeScript 来做,我们也应该自己做好判断。

假设上方的组件,在调用的时候 props 并没有给其传 categoryNo 值,我们又要采用,我们就应该给其赋初值。

const { pageRefresh, categoryNo = "01", inventoryScopeNo = "001" } = props;

或者说如下:

const { pageRefresh, categoryNo, inventoryScopeNo} = props || {
  	pageRefresh: ()=>void,
  	categoryNo: "01",
  	inventoryScopeNo: "001",
};

这样我们可以预判一些特殊的情况,从而让程序按照我们的想法来做。

3. 网络交互

除了做好组件的初始化,赋值工作外,更多时候,我们用某个组件都是要将数据放置到这个组件上去,这个时候,不仅仅在组件方面做好特殊情况的处理,在网络请求获取方面,也要做这样一个事情。

const { data ={ list: [] }, success } =
	await services.EmissonDataEntryController.queryDataEntryItemsList({
	dataEntryItemQueryRequest: {
		current,
		pageSize,
		inventoryScopeNo: INVENTORY_SCOPE_NO_RANGE_ONE,
		emissionCategoryNo: categoryNo,
	},
});
return {
		data: data?.list,
		success,
};

思考

但是这个地方,团队另外一个伙伴@牧亿 ,他给了我另外一个思考和想法,前端是否需要做这方面的内容。

某种意义上上,像是赋初值、出错的时候,应该展示的数据。这些真的应该展示么?

假设接口方面报错了,然后前端给了默认值,让用户觉得:哦,没有错哦,你看没有报错嘛!是不是不太好?这种问题,是否就是应该直接抛错误,或者说就是通过 errorMsg 这种报错弹窗弹出来,这也是一个值得思考的问题。

短期来看,我暂时无法判断出两者的好坏,我觉得两者都是可以接受的,后续会持续关注这个问题。

总结

不管怎么说,防御性编程的思想,一定要在开发中的点滴,要深入开发中的各种细节部分。

只有做好了这一块的内容,后续的开发才会更加顺利。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值