本来题目是想叫做《前端服务降级》的,但是本文内容跟服务器端的服务降级实现上并不相同,虽然思想上都是对服务异常的一些兜底策略。
背景
在个人业务或者一些小团队的项目中,业务主要是“能跑就行”,很多时候对于一些边界情况并不关心,但是用户的使用场景非常复杂,需要尽量完善业务链路,对服务进行质量管理。对提供的服务进行“服务降级”,提供相关兜底策略。
什么是服务降级?在百度百科中,服务降级是这么表示的(如下图),前端开发也需要在业务上对服务异常的时候进行一些兜底,防止用户使用的时候“懵住”。
服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。
在前端服务中有很多需要注意的地方,下面会给出几个案例,希望抛砖引玉,也希望大伙能在业务中尽量覆盖。
案例
图片崩溃
由于用户的网络非常复杂,我们图片很可能出现加载过慢,或者崩塌的情况,就算设置了alt
属性想进行兜底处理,但是效果还是不太理想。
此时,我们可以通过onerror
属性,操作event
进行默认图片的显示:
const App:React.FC = ()=> {
return (
<>
<img src="https:///avatar/6717291b8b60630568540a7a0206d621?d=retro" alt="image"
onError={(e)=>{
console.log("error",e);
// 这里用了掘金的logo,但是默认情况下,企业项目一般会有兜底的图片,没有的话,就让ui大佬帮忙弄一下
e.target.src = "https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/6c61ae65d1c41ae8221a670fa32d05aa.svg";
}}/>
</>
)
}
响应式图片
首先我们需要知道位图
和矢量图
的区别。在我存货中的一篇文章中是这么说的:
主要是,位图,原来渲染的1个像素点,伸缩之后就渲染不匹配数量的像素点,会有失真问题,而矢量图是公式计算出来的,不管怎么伸缩,都不会引起失真。
在mdn
上,就有相关案例
在案例网站中,对于大屏幕的显示是这样的: 对于H5显示的时候是这样的:
我们是否需要在屏幕像素比小的时候去有更好的显示呢?答案是:需要的
!
可以通过
可以通过js的手段获取屏幕像素比,设置响应式图片:
const App: React.FC = () => {
// 根据像素比确定要加载的图片路径
const [img, setImg] = useState("");
useEffect(() => {
const pixelRatio = window.devicePixelRatio || 1;
if (pixelRatio >= 2) {
// 如果像素比大于等于2,加载高清图
setImg(
"https://img0.baidu.com/it/u=3021883569,1259262591&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1695661200&t=6e189da4e5e99e2c9bd98215c15f5b2d"
);
} else {
// 如果像素比小于2,加载普通图
setImg(
"https://img2.baidu.com/it/u=3853345508,384760633&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1695661200&t=e038562a3374928980eee0f92dfdeb1c"
);
}
}, []);
return (
<>
<img src={img} alt="图片" />
</>
);
};
不同像素比的展示:
也可以通过img
的srcset
和sizes
属性展示:
<img
srcset="elva-fairy-480w.jpg 480w, elva-fairy-800w.jpg 800w"
sizes="(max-width: 600px) 480px,
800px"
src="elva-fairy-800w.jpg"
alt="Elva dressed as a fairy" />
网络请求重试和loading
在网络请求中,有可能遇到客户突然切换网络的情况或者服务器本次出错的情况。此时,用户本次的网络请求可能达不到预期结果,对于这种情况,我们可以判断设置重试次数并根据网络状态给出相应的提示。
在网络请求中,尽量给用户一个loading
效果,让用户知道,自己已经成功进行操作:
const App: React.FC = () => {
const [userList, setUserList] = useState([]);
const click = () => {
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.json())
.then((json) => {
console.log(json);
setUserList([...userList, json]);
});
};
return (
<>
<button onClick={click}>666</button>
{userList.map((user, index) => {
return <div key={index}>{JSON.stringify(user)}</div>;
})}
</>
);
};
在demo代码中,如果当navigator.onLine
的值为true
(有网络)的时候,预期效果还是很容易展示出来的
当设置网络状态为slow 3g
的时候,效果就会变得非常慢了,中间态的loading效果还是很有必要的。
本次分享的服务质量管理也是之前学习到的一个内容,真实的场景非常复杂,我们在代码中,需要合理的界定边界情况。在开发中覆盖力所能及的,剩下的场景就期待测试大佬帮忙覆盖了~