当前位置: 首页 > 后端技术 > Node.js

前端性能:如何破解炒股APP频繁更新

时间:2023-04-03 15:34:59 Node.js

写这篇文章的原因是最近有几个小伙伴来问这个问题。之前帮人回答过一次。今天写完之后,有时间再写更多的解决方案,比如Oom,不用esbuild怎么解决等等。正题正式开始:炒股APP(IM场景前端交互高-频率更新滞后)。一个普通的炒股APP是很复杂的,而且大部分都是原生写的,但是有的公司没钱,所以只能自己做一套webapp或者用RN写,我也用Flutter(这个是我没钱想玩的,怎么办呢?然后玩乞丐版)一个炒股app的界面首先,金融交易产品是一种IM产品,大部分使用基于TCP长链接或wss协议的私有协议。这里附上我之前写过的两篇文章,希望大家能更好的阅读这篇文章。手工实现一个websocket协议(基于Node.js)并手工编写一个React框架来重现问题。用户收藏了1000只自选股票(国内外+期货+指数等),技术栈为webapp,基于react或React-native,非常卡由于双工通信和高-频率推送,触发更新,交易APP对消息传递的效率/低延迟要求非常高。比如你准备买这只股票,这时候大户在卖,你还没收到。更新信息,下单,发现趋势变坏了,再拿单就被套住了。另一种情况是买的时候赚大了。你的订单价格是10元,但是此时已经涨到10.05了。这个价格卖不出去,就错过了一波大涨。这时候客户就惨了,因为react-native组件挂载后不会卸载,不像webapp。原则上性能优化最好使用所见即所得的简单手段,简单高中,不触及底层逻辑,比如网络层的前后端可能需要处理粘包...不要选择可能诱发P0级事故的技术方向,react不会,需要虚拟列表,推荐库react-peter-window,可以支持自动高宽源码演示地址:https://github.com/JinJieTan/react-keepAlive-dynamic这样react也可以跟react-Native组件一样,只渲染可见区域。长列表问题解决了,但是事件也很麻烦。理论上用户可以无限次添加自选股票,而这个列表可能无限长(不要说不可能,世界都在开发中,这是一个高可用的APP),传统事件需要绑定到每个item,然后在切换组件的时候移除,但是频繁的挂载和移除事件其实是性能上的损耗,这里不用事件冒泡,就是这样,把需要的数据挂载到dom的属性中就可以了~我说的以上,不要小看它,它可以解决相当一部分的性能问题,最主要的问题是高频更新。不同的金融交易公司,后台架构设计不同,消息推送也是如此。比如大智慧的后台架构就比较特别。前端网络层可能要处理粘包,后端消息推送的频率,不管PReact、Redis、Kafka的思路如何,都会在前端由我们自己实现。消息队列,定时消费,更新接口。参考我之前手写的React代码:`https://github.com/JinJieTan/mini-react/tree/hooksimport{_render}from'../reactDom/index';import{enqueueSetState}from'./setState';导出类组件{constuctor(props={}){this.state={};这个.props=道具;}setState(stateChange){constnewState=Object.assign(this.state||{},stateChange);console.log(newState,'newState')this.newState=newState;enqueueSetState(newState,this);}}`setState后,先入队,第一次进入,队列为空,入队判断,在下一帧渲染前调用defer(flush)`导出函数enqueueSetState(stateChange,component){//firsttimeyouenterissure会先调用defer函数if(setStateQueue.length===0){//清空队列的方式是异步执行,下面是一些同步执行的计算defer(flush);}//将对象key加入队列:stateChangevalue:componentsetStateQueue.push({stateChange,component,});//如果渲染队列中没有这个组件,则添加它if(!renderQueue.some((item)=>item===component)){renderQueue.push(component);}}`deferfunction`functiondefer(fn){//异步挂起高优先级任务returnrequestAnimationFrame(fn);}`此时再次推送消息,再次触发enqueueSetState,数据为此时push入队列,一帧被合并消费?其实浏览器也有一个渲染队列。比如你在for循环中频繁操作dom,不会导致浏览器每次操作dom都要渲染。当达到一个阈值时,就会触发渲染,当然你也可以手动控制队列的清空(这里讲的不算太深,有兴趣的可以关注后面的文章)?写在最后我是Peter,architecture设计了一款桌面端到端加密超群功能的IM软件,现为前端架构师。如果你对性能优化有深入的研究,可以和我交流。今天这里写的比较浅,但是一般人都能用。之前问过朋友,让他写一个timer定时消费队列,最后也有效。哈哈另外,欢迎收藏我的资料网址:前端生活社区:https://qianduan.life觉得对你有帮助,可以点击右下角观看,关注一波公众号的:【前端巅峰】