防止快速连续操作返回内容混乱

场景描述

这里通过几张截图,描述场景,废话少说,直接上页面截图:

图1: 分类列表 

通过这个组件可以选择分类,而且可以删除某个分类,也可以全部删除。



图2: 日均销售额预估图

(1)此处显示图1中所选择的分类对应的日均销售额预估值。

(2)图1中删除某个分类,或者全部删除,日均销售额预估列表也删除这几项。

(3)图1中新增某个或者某些分类,日均销售额预估列表也新增这几项,并通过请求获取分类对应的销售额预估



技术架构背景

react + redux + fetch

使用promise封装fetch请求


问题描述

1. 新增分类,发送请求获取日均销售额预估。该请求比较慢,且返回时间不可控。

比如快速点击新增了4个分类,请求是按照先后顺序发出的,但是最先发出的请求(包含1个分类时)可能返回最慢,而最后发出的请求(包含4个分类)却最早返回。

导致的问题是,最先发出的请求最后返回,页面显示的结果为最后返回请求的内容,也就是会显示只有一个分类。而图1分类列表的已选择内包含有4个分类。

见下图:



2. 删除操作,不发送网络请求。如果添加分类后,请求未返回时,执行了删除操作。那等请求返回后,被删除掉的分类还会显示到页面里。给用户的感觉就是 删不掉。。


思路描述

拦截历史请求。意思是快速发送10个请求,那么拦截前9次的请求,只处理第10个请求。


提出问题(关于ajax的abort和fetch的promise)

1. ajax中有一个abort方法,可以拦截请求:

var xhr = $.ajax(url);
xhr.abort();

2. 而fetch作为ajax的升级版,越来越多的浏览器已经支持他了,是fetch暂时不能被取消...,因为没有对应的api。

这里用promise如何实现abort呢?

promise仅有两个完成态,resolved和rejected。一个可以当做success处理,另一个可以当做error处理。一旦一个请求得到了响应,也就是promise执行后,不能执行abort,要么进入success处理,要么进error处理。

这里我们可以在success和error处理代码中,捕获到需要abort掉的请求(前9次历史请求),进行数据的单独处理,比如捕获到是历史请求,则该请求返回成功后,不对返回数据进行渲染等。

因此,本文给出的解决方案,并没有真正拦截请求,而是对需要被拦截的请求,进行返回数据的特殊处理。那么如何对返回数据进行特殊处理呢,请继续往下看……


解决方案

步骤一:

1. 在store中设置一个时间戳state,比如timeStamp:0默认值;

2. 每次新增分类时,都在action中发送一个当前请求的时间戳tempTimeStamp,并更新state中的timeStamp

下图是action中发送时间戳的操作.红框部分是删除操作对应的action,


然后,在reducer中执行删除分类,和新增分类操作,更新state中timeStamp,


3. 请求返回,不论成功还是失败,都会比较该请求和state中的timeStamp,如果timeStamp > tempTimeStamp,那么不处理该请求(请求成功的操作见上图,请求失败时的操作见下图);


提出问题:添加分类请求未返回时,执行删除操作,请求成功返回后,被删除项依旧显示到页面上

步骤二:(代码见步骤一)

1. 删除操作不设置时间戳,单独写一个action(与新增分类不共用action)

2. 每次删除操作,都立即更新state列表。当新增分类请求返回成功时,将返回值,与state中已选择分类列表 进行比较,如果返回值.length > 已选择列表.length,那么说明执行了删除操作,这是过滤掉返回值中多出的项
提出问题:当添加10个模板,就会发出10个请求。拦截前9个请求后,将最后一个请求结果(不论成功或失败)显示到页面上。这里实际上并没有真正的拦截请求,而是对历史请求返回结果不做处理。那么当前9个请求中存在失败的情况时,还是会报错,该如何拦截这里的请求呢?

步骤三(代码见步骤一):

1. 这个问题可能一些人不会遇到,或者没有看懂什么意思。没有关系的,这个疑问点,是和代码结构有关的

2. 这里我说下我的相关代码。这里写了一个公共组件,用来处理action中type和types时,dispatch的顺序。如const [REQUEST, SUCCESS, FAILURE] = types; 当请求成功时,会通过next方法,进入SUCCESS对应的reducer代码执行;当请求失败时,会先通过next方法,进入FAILURE对应的reducer代码执行,然后会进入报错代码;

3. 这里如果想要阻止历史请求(前9次请求)失败时报错,那么就将该请求对应的FAILURE,通过判断,在报错代码中排除掉。并在FAILURE对应的reducer代码中捕获errStatus,通过判断时间戳是否为历史请求,如果时,则不做处理;如果不是,则进行错误处理;

在reducer中捕获error,并进行处理的代码如下:


在公共组件的报错代码中排除掉该action,即:FETCH_GOODS_DAILYSALES_FAIL,代码如下:


如果有哪里没看明白,可以留言询问哈,这里涉及代码略多,不知道是否表达明白,欢迎询问

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值