前端React实现fetch取消、中止请求

场景:

项目开发过程中有时会遇到这种情况:两次查询请求相隔时间很短时,由于接口异步,第一次请求可能会覆盖第二次请求返回数据,所以需要在第二次请求前先将第一次请求中止,话不多说,实现如下:
关于axios取消请求网上有很多,可自信百度,本文主要针对于fetch请求,由于fetch并没有 “取消请求” 方法,目前通过AbortController()实现

项目:Ant.Design Pro + umijs + dva

新建一个abortDispath.js文件

export const abortDispatch = (payload, dispatch) => {
  if (payload && payload.signal) {
    const error = 'success! request is aborted';
    if (payload.signal.aborted) {
      // eslint-disable-next-line prefer-promise-reject-errors
      return Promise.reject(error); // 通过reject达到中止请求目的
    }
    const cancellation = new Promise((_, reject) => {
      payload.signal.addEventListener('abort', () => {
        // eslint-disable-next-line prefer-promise-reject-errors
        reject(error);
      });
    });
    return Promise.race([cancellation, dispatch(payload)]); //Promise.race比较中止和接口请求快慢,谁快返回谁
  }
  return dispatch(payload);
};

新建一个扩展Component

import React from 'react';

/**
 * 用于组件卸载时自动cancel所有注册的promise
 */
export default class EnhanceComponent extends React.Component {
  constructor(props) {
    super(props);
    this.abortSignalControllers = [];
  }

  componentWillUnmount() {
    this.abortSignalControl(); // 页面卸载后自动中止所有请求
  }

  /**
   * 注册control
   */
  bindSignalControl = () => {
    let registerSignal = '';
    if ('AbortController' in window) {
      const controller = new AbortController();
      const { signal } = controller;
      registerSignal = signal;
      this.abortSignalControllers.push(controller);
    }
    return registerSignal;
  };

  /**
   * 取消signal对应的Promise的请求
   * @param {*} signal
   */
  abortSignalControl(signal) {
    if (signal !== undefined) {
      const idx = this._findSignalControl(signal);
      if (idx !== -1) {
        const control = this.abortSignalControllers[idx];
        control.abort();
        this.abortSignalControllers.splice(idx, 1);
      }
    } else {
      this.abortSignalControllers.forEach(control => {
        control.abort();
      });
      this.abortSignalControllers = [];
    }
  }

  _findSignalControl(signal) {
    const idx = this.abortSignalControllers.findIndex(controller => controller.signal === signal);
    return idx;
  }
}

demo.js

export default class Demo extends EnhanceComponent{
	constructor(props) {
	    super(props);
	    this.state = {
	      signal: this.bindSignalControl(),
	    };
	}
	
	search = () => {
		this.abortSignalControl(this.state.signal); // 请求前先中止上一次的请求
		const payload = {
			...其他参数
			signal: this.bindSignalControl()
		}
		this.setState({
      		signal: payload.signal, // 保存最新的signal
    	});
		abortDispatch(payload, query =>
      		dispatch({
				type: 'xxx',
				payload: {...query},
				callback: (data, aborted) => {
					if (!aborted) {
						// !aborted避免页面卸载后或者中止请求后进行this.setState
					}
				}
			})
	}
}

request.js文件中需要将signal放在options中,例如

在errorHandler方法中对Aborted接口进行特殊处理
const errorHandler = error => {
  const { response, data, name } = error || {};
  const { status, url = '', statusText } = response || {};
  // 如果是终止请求,默认返回成功
  if (name === 'AbortError') {
    return {
      code: 0, // 请求成功
      aborted: true, // callback页面是否中止请求成功
    };
  }
return { response, data };
}
  
const request = extend({
  errorHandler,
  prefix: '/api',
})
request.interceptors.request.use((url, options) => {
 return {
      url,
      options: {
        ...options,
        signal: options.signal
      },
    };
})

热门文章

暂无图片
编程学习 ·

HTTP权威指南------1.1HTTP概述

HTTP权威指南------HTTP概述HTTP概述C/S媒体类型URIURLURN事务方法状态码报文连接版本历程Web的结构组件代理缓存网关隧道用户代理 HTTP概述 HTTP是可靠数据传输协议,其传输过程确保数据的完整正确,无需进一步关注传输过程的控制。 C/S 客户端与服务器架构,服务器存储相应的…
暂无图片
编程学习 ·

如何将PDF转换成jpg图片?教你2种免费方法

如何将PDF格式的文件转换成JPG图片?有时为了方便需要将PDF转成图片来使用,直接截图不仅耗费时间,而且像素很不清晰,有没有其他方便快捷转出高清图片的方法呢? 方法1: 这个方法最方便就在于不用下载安装软件,甚至都不需要注册登录,只要有网络,手机和电脑都能快速操作完…
暂无图片
编程学习 ·

linux安装nginx及https化

Linux安装nginx安装操作系统:centos 安装前先确保系统安装了g++、gcc、openssl-devel、pcre-devel和zlib-devel软件yum install gcc-c++ yum -y install zlib zlib-devel openssl openssl--devel pcre pcre-devel上传nginx安装包nginx-1.13.0.tar.gz至linux指定位置(/usr/loc…
暂无图片
编程学习 ·

React配置less以及less的全局变量设置

工作中接触react的项目比较的少,对于less的全局变量设置在vue项目中设置过,react的全局变量设置没怎么接触了。 看到有小伙伴问这个,试着在网上找了下,也是花费了不少的功夫才找到不错的方式,在这里分享给大家。 由于之前vue项目里没法使用sass-resource-loader,一开始也…
暂无图片
编程学习 ·

【项目总结】第三方OA对接、项目从零入手

前言近半年在平台项目的接触过程中,发现底层源码的能力很重要,有助于帮助我们理解项目代码,整理思路。代码思维能力也很重要。 项目经历 一、开发内容 第三方对接 华为云WeLink对接 2019-12 ~ 2020-04 企业微信小程序对接 2020-03 ~ 2020-05 好视通视频会议对接 2020-0…
暂无图片
编程学习 ·

Python——走马灯

走马灯 def f():import times=人生苦短,我学Pythonc=0while True:print(s)time.sleep(0.3)#休眠0.3秒。每隔0.3秒,即300毫秒显示一行代码s=s[1:]+s[0]c+= 1if c==2*len(s):break f()输出结果 人生苦短,我学Python 生苦短,我学Python人 苦短,我学Python人生 短,我学Python…
暂无图片
编程学习 ·

「干货教程」朋友圈装X神器!超级辅助-微信跳一跳

简介这个外挂原理比较简单,通过adb驱动链接到手机,通过图片识别实现模拟用户操作,通过计算方块像素实现得到下一个方块的坐标,跳到下一个点的位置设一个随机数.**环境配置首先我们先把adb驱动给配置好右键单击此电脑高级系统设置双击Path点击浏览把adb文件夹包含进来,也可以复制…
暂无图片
编程学习 ·

Tableau制作全球电影数据分析/全球超市利润混合地图

作业5: 1、创建产地电影数量与评分(以此命名)的符号地图,处理未知位置信息,以颜色表示评分平均值,选择红绿发散,以电影数量表示圆形大小,显示产地标签,对数据进行分析。 2、使用智能显示制作连续面积图,命名为电影数量变化,以年代为横轴,电影数量为纵轴,显示标签;…
暂无图片
编程学习 ·

Linux下core dump学习

参考链接 在linux下开发时,如果程序突然崩溃了,也没有任何日志。这时可以查看core文件。从core文件中分析原因,通过gdb看出程序挂在哪里,分析前后的变量,找出问题的原因。 1 查看linux下core dump是否开启 在linux上coredump默认是关闭的,可以通过ulimit -c查看,如果输出…
暂无图片
编程学习 ·

VMware上安装达梦数据库8.0

VMware上安装达梦数据库8.0 VMware上安装达梦数据库8.0 本文指导达梦数据库8.0版本的安装,安装环境为中标麒麟7操作系统 第一步: 操作系统界面右键进入终端控制台,如下图所示:第二步: 规划dm8安装路径:首先,查看磁盘信息是否满足,如下图所示;2. 新建dm8安装目录,如下…
暂无图片
编程学习 ·

简单动态字符串

SDS(simple synamic String)用作Redis默认字符串表示。C字符串只会作为字符串字面量用在一些无须对字符串进行修改的地方,例如打印日志等。 SDS定义 每个sds.h/sdshdr结构表示一个SDS值 struct sdshdr {//字符串的长度int len;// buf数组中未使用字节的数量int free;// 字节…
暂无图片
编程学习 ·

linux jdk1.8安装

jdk安装安装包下载 https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.htmljdk-8u151-linux-x64.tar.gz解压 tar -zxf jdk-8u151-linux-x64.tar.gz[root@vm051centos data]# ls jdk1.8.0_151/ bin db javafx-src.zip lib man …
暂无图片
编程学习 ·

RocketMQ消费者之消息消费过程分析

心跳机制在Consumer启动后,它就会通过定时任务不断地向RocketMQ集群中的所有Broker实例发送心跳包心跳包内容包含了消息消费分组名称订阅关系集合消息通信模式客户端id的值Broker端在收到Consumer的心跳消息后,会将它维护在ConsumerManager的本地缓存变量—consumerTable,同…
暂无图片
编程学习 ·

斐波那契数列

斐波那契数列 是在13世纪有数学家斐波那契发现,并因此命名的 。 即‘0,1,1,2,3,5,8,13,21,34,55,89…’; 即第N个值是第(N-1)与(N-2)的值的和;