不愧是前端老油条,分分钟看出我方案的bug

2023-10-30 16:20

本文主要是介绍不愧是前端老油条,分分钟看出我方案的bug,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击上方关注 前端技术江湖,一起学习,天天进步

国庆前刚开发完一个小需求,常规性的做了一次code review,不过这次review有所不同,我们组前端老油条竟然参会了,平时发会邀都不来的。

不过不愧是老油条,竟然分分中发现了问题,老油条的地位又在我们小前端的心里巩固了一下。

和往常一样,review前先过一遍技术方案,一让大家快速的了解需求,二来分析下技术方案是否存在问题,是否合理,一般情况下,技术方案没问题,后面的代码review感觉就没啥必要了,因为很少有人听。

e8f2594a8bcce21068b8eae254560ff6.png

就在刚要讲完技术方案,要进入review代码阶段,老油条提出了问题,我心想这么简单的需求会有啥问题?

到这里我不得不把需求搬出来,让各位看官瞅瞅,一起来看是否存在这样的问题,换作是你,你会怎样处理。

需求超简单,上截图

64c189dfc1b97c3bd38a25b7c0187591.png
image.png

上面是一个分类数据展示页面,左侧是一级分类,右侧二级分类和三级分类,然后下面是推荐的商品列表。

就这样一个页面会有什么问题呢?撑死2个接口,一个分类接口,一个商品推荐接口。

问题在于交互上,左边的一级分类可以随意切换,如果用户不讲武德,不等右边的数据渲染完就切换了,那会给用户带来什么体验呢?

会导致渲染结果混乱,旧数据渲染在了新的分类里。

解决方案

其实很简单,切换分类时,取消上一个请求。

怎样实现取消请求呢?

下面咱们就来总结性的看下如何取消一个请求,看哪个方式更简单易用。

思路:项目中的网络请求模块一般都是基于promise进行封装,返回一个promise对象,其实只要把 promise 取消掉就可以,其实并不是真正的取消网络请求,而是丢弃返回的数据。

方法1 - 借助reject方法

fe都知道一个promise对象状态的改变是通过resolve和reject来执行的。那是不是可以借助reject方法来模拟呢?

//返回一个promise和abort方法
function getPromise() {let _res, _rej;const promise = new Promise((resolve, reject) => {_res = resolve;_rej = reject;setTimeout(() => {resolve('123')}, 5000);});return {promise,abort: () => {_rej({name: "abort",message: "the promise is aborted",aborted: true,});}};
}const { promise, abort } = getPromise();
promise.then(console.log).catch(e => {console.log(e);
});abort();

上面的方法可以正常执行,但是不够通用,可以将Promise构造函数内的逻辑提取出来,作为一个回调传进去。

改造后

function getPromise(cb) {let _res, _rej;const promise = new Promise((res, rej) => {_res = res;_rej = rej;cb && cb(res,rej);});return {promise,abort: () => {_rej({name: "abort",message: "the promise is aborted",aborted: true,});}};
}//主逻辑提取出来
function runCb(resolve,reject){setTimeout(()=>{resolve('1111')},3000)
}const { promise, abort } = getPromise(runCb);
promise.then(console.log).catch(e => {console.log(e);
});

方法2  - 借助 Promise.race()

简单复习下race方法的作用,当有若干个promise, p1, p2, p3…在调用, let p = Promise.race([p1, p2, p3,…])的时候,返回的p也是一个promise。那么p什么时候会被resolve或者被reject呢?

看race单词的意思就知道它是竞速或赛跑的意思,所以p1, p2, p3 … 最先一个被resolve或者被reject的结果就是p的resolve或者reject的结果。所以后续的promise的resolve和reject都不会再被执行了。

代码很简单,但足够短小精悍。

//传入一个正在执行的promise
function getPromiseWithAbort(p){let obj = {};//内部定一个新的promise,用来终止执行let p1 = new Promise(function(resolve, reject){obj.abort = reject;});obj.promise = Promise.race([p, p1]);return obj;
}

调用~

var promise  = new Promise((resolve)=>{setTimeout(()=>{resolve('123')},3000)
})var obj = getPromiseWithAbort(promise)obj.promise.then(res=>{console.log(res)})//如果要取消
obj.abort('取消执行')
6b6bacd9bfe523dd404c836f346c9c85.png
image.png

借助race方法明显的更简洁,更易用。

最后

取消promise执行和取消请求是一样的,并不是真的终止了请求的执行,而是丢弃了数据,对结果不再处理。另外fetch api虽然增加了新的标准实现(AbortSignal),但仍然存在兼容问题,而且只能在浏览器中使用。那么非浏览器的环境中呢?比如RN?小程序?所以如果想要达到一种通用的方式,那么本文的reject promise的方式应该是个不错的方式。

此时我看着11点方向的前端老油条,肃然起敬,摆正自己的态度,多向前辈学习,做了这么多年的业务还能保持这样的敏锐度。

拿起手机疯狂的自测起自己的需求,忽然发现了一个性能问题,频繁切换竟然会卡。

为啥卡?怎么解决?

e6422a20fa8e9f79cb46c9587f474e33.png

欢迎留言讨论。

The End

欢迎自荐投稿到《前端技术江湖》,如果你觉得这篇内容对你挺有启发,记得点个 「在看」

点个『在看』支持下 294c7a00b512a3e62579beafaff9e161.gif

这篇关于不愧是前端老油条,分分钟看出我方案的bug的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/309135

相关文章

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

SQLite3 在嵌入式C环境中存储音频/视频文件的最优方案

《SQLite3在嵌入式C环境中存储音频/视频文件的最优方案》本文探讨了SQLite3在嵌入式C环境中存储音视频文件的优化方案,推荐采用文件路径存储结合元数据管理,兼顾效率与资源限制,小文件可使用B... 目录SQLite3 在嵌入式C环境中存储音频/视频文件的专业方案一、存储策略选择1. 直接存储 vs

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

HTML中meta标签的常见使用案例(示例详解)

《HTML中meta标签的常见使用案例(示例详解)》HTMLmeta标签用于提供文档元数据,涵盖字符编码、SEO优化、社交媒体集成、移动设备适配、浏览器控制及安全隐私设置,优化页面显示与搜索引擎索引... 目录html中meta标签的常见使用案例一、基础功能二、搜索引擎优化(seo)三、社交媒体集成四、移动

HTML input 标签示例详解

《HTMLinput标签示例详解》input标签主要用于接收用户的输入,随type属性值的不同,变换其具体功能,本文通过实例图文并茂的形式给大家介绍HTMLinput标签,感兴趣的朋友一... 目录通用属性输入框单行文本输入框 text密码输入框 password数字输入框 number电子邮件输入编程框

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h

CSS3打造的现代交互式登录界面详细实现过程

《CSS3打造的现代交互式登录界面详细实现过程》本文介绍CSS3和jQuery在登录界面设计中的应用,涵盖动画、选择器、自定义字体及盒模型技术,提升界面美观与交互性,同时优化性能和可访问性,感兴趣的朋... 目录1. css3用户登录界面设计概述1.1 用户界面设计的重要性1.2 CSS3的新特性与优势1.

HTML5 中的<button>标签用法和特征

《HTML5中的<button>标签用法和特征》在HTML5中,button标签用于定义一个可点击的按钮,它是创建交互式网页的重要元素之一,本文将深入解析HTML5中的button标签,详细介绍其属... 目录引言<button> 标签的基本用法<button> 标签的属性typevaluedisabled

HTML5实现的移动端购物车自动结算功能示例代码

《HTML5实现的移动端购物车自动结算功能示例代码》本文介绍HTML5实现移动端购物车自动结算,通过WebStorage、事件监听、DOM操作等技术,确保实时更新与数据同步,优化性能及无障碍性,提升用... 目录1. 移动端购物车自动结算概述2. 数据存储与状态保存机制2.1 浏览器端的数据存储方式2.1.

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,