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

简介: 国庆前刚开发完一个小需求,常规性的做了一次code review,不过这次review有所不同,我们组前端老油条竟然参会了,平时发会邀都不来的。不过不愧是老油条,竟然分分中发现了问题,老油条的地位又在我们小前端的心里巩固了一下。和往常一样,review前先过一遍技术方案,一让大家快速的了解需求,二来分析下技术方案是否存在问题,是否合理,一般情况下,技术方案没问题,后面的代码review感觉就没啥必要了,因为很少有人听。

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

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

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

f4276b88ac692a284d6b60cddb3d92eb_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

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

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

需求超简单,上截图

26b58190806ecc4d7d8ccd2ba8df0f1d_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.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('取消执行')

b0ee473dfe1289f811ae6ada775e4841_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

image.png

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

最后


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

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

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

目录
相关文章
|
3月前
|
Web App开发 缓存 前端开发
前端性能优化方案有哪些?
前端性能优化方案有哪些?
114 1
|
9月前
|
前端开发 JavaScript
常见的8个前端防御性编程方案
常见的8个前端防御性编程方案
109 0
|
10月前
|
前端开发 安全 程序员
测试大姐趁我下班点又提了个bug!前端你咋多个options请求?
测试大姐趁我下班点又提了个bug!前端你咋多个options请求?
68 0
|
5天前
|
缓存 前端开发 JavaScript
前端性能优化方案
【8月更文挑战第15天】前端性能优化方案
11 2
|
1月前
|
缓存 前端开发 JavaScript
前端常见的性能优化方案?
【7月更文挑战第14天】前端性能优化包括代码压缩、资源合并、图片优化、缓存策略和DOM操作改进。例如,压缩CSS、JS,懒加载图片,使用CDN,事件委托,启用HTTP/2,及利用性能工具进行评估和优化。目标是加快加载速度,提升用户体验和服务器效率。
40 2
|
1月前
|
缓存 前端开发 JavaScript
前端性能优化都有那些方案 ?
【7月更文挑战第11天】 前端性能优化包括资源合并压缩、懒加载、CDN使用、代码优化、缓存利用和图片优化等策略。例如,减少HTTP请求、压缩CSS/JS、事件委托、利用浏览器及服务器缓存、选择合适图片格式等,旨在提升网页速度和用户体验。服务工作者、异步加载和响应式设计也是关键。持续学习新技术以适应不断变化的优化需求。
37 1
|
18天前
|
存储 开发框架 前端开发
EAV模型(实体-属性-值)的设计和低代码的处理方案(3)-- 实体属性定义及前端列表展示和数据录入处理
EAV模型(实体-属性-值)的设计和低代码的处理方案(3)-- 实体属性定义及前端列表展示和数据录入处理
|
26天前
|
存储 前端开发 JavaScript
前端菜单及按钮权限拦截,实现方案及思路
此实现方案基于vue框架,并需要依赖vue项目相关的库,router、store等等;前端同学要与后端同学协商,常规是让后端返回一个树结构的菜单数据,并且将所有的涉及权限控制的页面path给到后端,如果是按钮,需要把所有的按钮 code 码统一下,这是前期工作,很重要。
|
1月前
|
前端开发 JavaScript 流计算
前端 JS 经典:打印对象的 bug
前端 JS 经典:打印对象的 bug
26 0
|
2月前
|
前端开发 安全 JavaScript
如何区分是前端BUG还是后端BUG
1 基于经验 前端BUG特点: (1)界面排版、布局错误、兼容性问题 (2)网络不稳定导致JS或CSS未完全加载或请求超时(一般不需要提BUG),正常网络下加载超时 后端BUG特点: 业务逻辑、性能问题、数据问题、安全性问题 2 通过HTTP请求和响应信息 可以通过浏览器开发者工具(F12)、postman、fiddler(移动端可通过该工具抓包)、Charles、Proxyman、Wireshark、HttpCanary、tcpdump等工具。
46 1