正在向服务端请求中 ajax 如何手动取消请求

在请求发送过程中,服务器返回请求之前我们可以手动取消请求。

原生ajax

可以通过请求对象的abort()方法来取消请求。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button>点击发送</button>
    <button>点击取消</button>
    <script>
        // 获取元素;
        const btns = document.getElementsByTagName('button');
        let xhr = null
        // 发送请求
        btns[0].onclick =function (){
      
      
            xhr = new XMLHttpRequest();
            xhr.open('GET','http://127.0.0.1:8000/delay')
            xhr.send()   
        }
        // abort取消请求
        btns[1].onclick = function (){
      
      
           xhr.abort();
        }
         
    </script>
</body>
</html>

axios

方式:

1、AbortController:从v0.22.0开始,axios支持以 fetch API方式——AbortController取消请求,用此方式一定要注意axios的版本,v0.22.0以下失效

2、cancelToken:此 API 从 v0.22.0 开始已被弃用,不应在新项目中使用。不过我的axios当前版本v1.2.0,还可以使用cancelToken

如果想了解fetch和ajax的区别,可以看这篇文章:https://zhuanlan.zhihu.com/p/401232894

AbortController 接口表示一个控制器对象,允许你根据需要中止一个或多个 Web 请求。

看一下MDN上官方文档示例:

let controller;
const url = 'video.mp4';

const downloadBtn = document.querySelector('.download');
const abortBtn = document.querySelector('.abort');

downloadBtn.addEventListener('click', fetchVideo);

abortBtn.addEventListener('click', () => {
    
    
  if (controller) {
    
    
    controller.abort();
    console.log('中止下载');
  }
});

function fetchVideo() {
    
    
  controller = new AbortController();
  const signal = controller.signal;
  fetch(url, {
    
     signal })
    .then((response) => {
    
    
      console.log('下载完成', response);
    })
    .catch((err) => {
    
    
      console.error(`下载错误:${
      
      err.message}`);
    });
}

在axios中使用

this.abortController = new AbortController();
const res = await http({
    
    
	url: 'http://0.0.0.0:8088',
	method: 'get',
	signal: this.abortController.signal,  // 带上参数
	params: {
    
    
		
	}
}).catch((err) => {
    
    
	this.isRequesting3 = false;
	console.log(err);
})

在取消方法中直接调用

this.abortController.abort();

在这里插入图片描述
在这里插入图片描述

取消多次重复请求

httpRequest.js

import axios from 'axios'
import store from '@/store'
import {
    
     message } from 'ant-design-vue'
 
const CancelToken = axios.CancelToken
 
let pedding = {
    
    }
 
const service = axios.create({
    
    
  baseURL: '/',
  timeout: 60000,
})
 
service.interceptors.request.use(config => {
    
    
  config.headers['token'] = store.state.user.token
 
  // 在参数中加个isCancelToken,用来判断该接口是否需要做多次请求取消上一个请求的操作
  if (config.isCancelToken) {
    
    
 
    // 第一种 AbortController
    const controller = new AbortController();
    config['signal'] = controller.signal
    pedding[config.url + '&' + config.method] && pedding[config.url + '&' + config.method].abort()
    pedding[config.url + '&' + config.method] = controller
 
    // 第二种 CancelToken.source
    const source = CancelToken.source()
    config['cancelToken'] = source.token
    pedding[config.url + '&' + config.method] && pedding[config.url + '&' + config.method].cancel()
    pedding[config.url + '&' + config.method] = source
 
    // 第三种 CancelToken
    pedding[config.url + '&' + config.method] && pedding[config.url + '&' + config.method]()
    config['cancelToken'] = new CancelToken((c) => {
    
    
      pedding[config.url + '&' + config.method] = c
    })
 
  }
 
  return config
}, error => {
    
    
  return Promise.reject(error)
})
 
service.interceptors.response.use(response => {
    
    
  // 这里删除key
  pedding[response.config.url + '&' + response.config.method] && delete pedding[response.config.url + '&' + response.config.method]
 
  if (response.data.code == 200) {
    
    
    return response.data
  } else {
    
    
    message.error(response.data.msg)
    return Promise.reject(response.data)
  }
}, error => {
    
    
  return Promise.reject(error)
})
 
export default service

以上三种方式选一个就可以。

使用
home.vue

<template>
  <div>
    <a-button>home</a-button>
    <router-link to="/about">跳转about</router-link>
    <a-input placeholder=""></a-input>
    <a-checkbox></a-checkbox>
  </div>
</template>
 
<script>
import {
      
       login } from '@/axios/api/home'
export default {
      
      
  setup() {
      
      
    login({
      
      timeRange: 'ONE_DAY'}).then(res => {
      
      
      console.log('第一次调用-success')
    }).catch((err) => {
      
      
      console.log('第一次调用-err')
    })
    setTimeout(() => {
      
      
      login({
      
      timeRange: 'ONE_DAY', num: 1}).then(res => {
      
      
        console.log('第二次调用-success')
      }).catch((err) => {
      
      
        console.log('第二次调用-err')
      })
    }, 200)
  }
}
</script>
 
<style lang="scss" scoped>
</style>

home.js

import request from '@/axios'
 
export const login = (data) => {
    
    
  return request({
    
    
    url: '/dc/pc/heatMap',
    method: 'get',
    params: data,
    isCancelToken: true
  })
}

保证多个请求按顺序返回

  1. 使用promise.all
  2. 请求接口中带个index标识符,和后端约定下返回数据中带上,拿到结果后做排序处理

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/woyebuzhidao321/article/details/129732967