关于列表项添加删除过程中有过长请求等待中怎么处理?

上面是一个简单的添加删除列表项功能,当我们输入内容确定后,请求时间会很长,当我们再次确定或者删除当前项再添加的时候,可能会由于数据返回的先后顺序,出现顺序错乱。

首先,请求时间过长的处理:

由于请求时间太长,删除或者重新确认的时候,之前的请求还挂着,所以我们应该把之前挂着的请求给终止掉,这里我们用到了AbortController去终止请求,我们可以写一个公共的方法如下:

javascript 复制代码
import qs from "qs";

export const getPendingUrl = (config) =>
  [config.method, config.url, qs.stringify(config.data)].join("&");

export class RequestAbort {
  constructor() {
    this.pendingMap = {};
  }
  addPending(config, key) {
    const mapValues = this.pendingMap[key] || new Map();
    this.pendingMap[key] = mapValues;
    const signalAbortName = getPendingUrl(config);
    if (!mapValues.has(signalAbortName)) {
      const controller = new AbortController(); // 创建一个控制器
      mapValues.set(signalAbortName, controller);
      return controller;
    }
  }
  // 清除请求
  removePending(config, key) {
    const mapValues = this.pendingMap[key];
    const signalAbortName = getPendingUrl(config);
    if (mapValues.has(signalAbortName)) {
      // 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除
      const controller = mapValues.get(signalAbortName);
      controller.abort();
      mapValues.delete(signalAbortName);
    }
  }
  // 清除对应值的map
  removeFinish(key, value) {
    const mapValues = this.pendingMap[key];
    mapValues && value && mapValues.delete(value)
  }
  // 根据类型key清除
  removeKeyPending(key) {
    const removeValues = this.pendingMap[key];
    if (removeValues) {
      removeValues.forEach((controller) => {
        controller && controller.abort();
      });
      removeValues.clear();
    }
  }
  // 清空
  removeAllPending() {
    this.pendingMap.forEach((item, key) => {
      removeKeyPending(key);
    });
    this.reset();
  }
  // 重置
  reset() {
    this.pendingMap = {};
  }
}

上面我们根据请求的方法、地址、参数作为独立的siganal来处理,getPendingUrl正是做这样子的处理。整个RequestAbort方法是为了处理根据不同请求添加到对应map组,终止对应的请求,或者终止全部请求。比如在我们离开当前页面,但是还有请求处理中,就可以全部清掉。

其次,怎么获取独一无二的请求?

我们在添加删除的时候,我们有可能输入框的参数是一样的,如果按照单存的index来区分,可能会出现顺序错乱,这时候我们就需要唯一值,那么怎么生成唯一值呢?我们可以通过通用的一些方法生成uuid,作为每一个添加的列表项的唯一id,生成uuid的方法如下:

ini 复制代码
// 生成uuid
const hexList = [];
for (let i = 0; i <= 15; i++) {
  hexList[i] = i.toString(16);
}
export const buildUUID = () => {
  let uuid = '';
  for (let i = 1; i <= 36; i++) {
    if (i === 9 || i === 14 || i === 19 || i === 24) {
      uuid += '-';
    } else if (i === 15) {
      uuid += 4;
    } else if (i === 20) {
      uuid += hexList[(Math.random() * 4) | 8];
    } else {
      uuid += hexList[(Math.random() * 16) | 0];
    }
  }
  return uuid.replace(/-/g, '');
}

如果在react中,我们初始state的时候我们就可以根据uuid初始化值,添加的时候通过生成uuid去添加数组值,删除根据uuid去删除如下:

javascript 复制代码
class Test extends Component {
    constructor(props) {
        super(props);
        const initUUID = buildUUID();
        this.state = {
          linkArray: [
            { value: "",uid: initUUID },
          ]
        };
    }
    // 添加
   handleAddLink = () => {
    const newLinkArray = _.cloneDeep(this.state.linkArray);
    const initUUID = buildUUID();
    newLinkArray.push({
      value: "",
      uid: initUUID,
    });
    this.setState({
      linkArray: newLinkArray,
    });
  };
  // 删除
    handleDelete = (uid) => {
    const { linkArray } = this.state
    const newLinkArray = _.cloneDeep(linkArray);
    const index = _.findIndex(newLinkArray, (item) => item.uid === uid);
    newLinkArray.splice(index, 1);
    this.setState({
      linkArray: newLinkArray,
    });
  };
  render() {
      const {linkArray } = this.state;
      return (<div>
          {linkArray.map((item, index) => (
            <div className={styles.linkInputItem} key={item.uid}></div>
            </div>
          ))}
      </div>)
  }
}
最后是我们在请求中的处理:
php 复制代码
import { RequestAbort, getPendingUrl } from "@/utils/abortRequest"

// 创建取消实例
const requestAbort = new RequestAbort()

export const apiRequest = (data) => {
  // 添加取消控制器
  const signalName = getPendingUrl({ method: "post", url: "url", data: data})
  const controller = requestAbort.addPending({ method: "post", url: "url", data: data},'type')
  return request("url", {
    method: "post",
    data,
    signal: controller?.signal,
  });
}
// 取消
export const cancelRequest = async (data) => {
  if(data) {
    return requestAbort.removePending({ method: "post", url: "url", data: data, 'type')
  } else {
    return requestAbort.removeKeyPending('type')
  }
}
相关推荐
nice先生的狂想曲3 小时前
javascript高级程序设计(六)——2026.9.5
前端·javascript
我爱写代码i3 小时前
SKAPP SK影视反编译详细教程+源码 含苹果端ipa
开发语言·javascript·ecmascript
光影少年3 小时前
如何做大型React+RN 项目架构设计、目录规范
前端·react native·react.js
yyt3630458413 小时前
KLineChartQuant:GLSL 的精度问题及 RTC 解法
前端·vue.js·react.js·交互·图形渲染·webgl·数据可视化
এ慕ོ冬℘゜3 小时前
前端实战:基于jQuery递归实现通用树形组织菜单(可直接复用)
前端·javascript·jquery
变与不变8064 小时前
js函数与封装详细解答
前端·javascript·vue.js
AZaLEan__5 小时前
事件循环讲解
javascript
变与不变8065 小时前
引用类型、内存原理与对象
开发语言·前端·javascript
Highcharts5 小时前
Highcharts实战讲解|散点图+多项式回归曲线复杂图表示列Demo
javascript·数据可视化
梨想橙汁5 小时前
Git 常用命令大全:提交、查看日志、版本回退、文件撤销
前端·javascript