惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

PCI Perspectives
PCI Perspectives
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Palo Alto Networks Blog
S
Schneier on Security
Scott Helme
Scott Helme
T
Threat Research - Cisco Blogs
K
Kaspersky official blog
Microsoft Azure Blog
Microsoft Azure Blog
T
The Exploit Database - CXSecurity.com
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tenable Blog
G
GRAHAM CLULEY
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
I
Intezer
D
Docker
月光博客
月光博客
L
Lohrmann on Cybersecurity
Latest news
Latest news
B
Blog
罗磊的独立博客
M
MIT News - Artificial intelligence
S
Securelist
Know Your Adversary
Know Your Adversary
Help Net Security
Help Net Security
Recorded Future
Recorded Future
S
SegmentFault 最新的问题
N
Netflix TechBlog - Medium
T
Threatpost
H
Hacker News: Front Page
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
人人都是产品经理
人人都是产品经理
F
Fortinet All Blogs
博客园 - Franky
P
Proofpoint News Feed
大猫的无限游戏
大猫的无限游戏
Blog — PlanetScale
Blog — PlanetScale
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
A
About on SuperTechFans
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tor Project blog
Google Online Security Blog
Google Online Security Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Engineering at Meta
Engineering at Meta
Webroot Blog
Webroot Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Microsoft Security Blog
Microsoft Security Blog

静水深流's blog

探索 SSE:服务器推送技术的魅力与应用 | 静水深流 图解DIFF算法介绍 | 静水深流 如何使用javascript实现复制出的文案带链接? | 静水深流 基于vuepress2搭建专属自己的博客,并集成各种常用功能 | 静水深流 听说你至今不晓得缓存淘汰算法?实现LRU、LFU和FIFO? | 静水深流 最长递增子序列及vue3.0中diff算法 | 静水深流 二进制之入门到应用实践 | 静水深流 常见算法学习 | 静水深流 CSS 形状的实现 | 静水深流 前端常见的安全问题 | 静水深流 关于http服务端的学习&总结 | 静水深流 前端面试题总结 | 静水深流 javascript原生代码实现及代码总结 | 静水深流 LeetCode算法学习总结-简单 | 静水深流 LeetCode算法学习总结-困难 | 静水深流 LeetCode算法学习总结- 中等 | 静水深流 排序算法总结 | 静水深流 扫码登录的实现原理 | 静水深流 Javascript之常见类型判断汇总 | 静水深流 JavaScript各种继承方式和优缺点 | 静水深流 webpack开发、使用及优化总结 | 静水深流 从JavaScript中的拷贝开始思考 | 静水深流 vue原理、使用及面试方面的总结 | 静水深流 前端发展及选择 | 静水深流 css面试总结 | 静水深流 JavaScript 数组展开(扁平化)和underscore的 flatten | 静水深流 首页 | 静水深流 学习网站收藏 | 静水深流 文章列表 | 静水深流
ajax取消接口请求 | 静水深流
shaolibao · 2022-07-12 · via 静水深流's blog

原生ajax中取消请求的方法

const xhr = new XMLHttpReques()
xhr.open('GET', '/api')
xhr.onreadstatechange(() => {
  if(xhr.readState === '4' && /^2\d{2}/.test(xhr.status)) {
    // sucess
  }
})
xhr.send()

// 取消请求
xhr.abort()

axios中取消同一时间的多次请求

最常见的案例就是当我们点击按钮需要去请求数据,如果按钮没有坐任何限制的话,当快速多次点击按钮,可能会同时发出好几条相同的请求,造成服务器压力,也有可能造成页面数据不对,此时我们一般常用的方法就是在axios的全局拦截中做一些限制和判断来规避这种操作 方法一:防止多次重复的请求

import axios from 'axios'

// 将正在请求的地址存储起来
const pending = []
const CancelToken = axios.CancelToken
/**
 * config 请求的axios的配置信息
 * c框架中用于取消的回调,在这也会用来判断当前是请求阶段还是返回阶段
*/
const removePending = (config, c) => {
  const url = config.url
  const index = pending.findIndex(i => i === `${url}&${config.method}`)
  // 判断要请求的的地址有没有在pending中
  if (index > -1) {
    c ? c('数据请求中……') : pending.splice(index, 1)
  } else {
    c && pending.push(`${url}&${config.method}`)
  }
}
// 超时设置
axios.defaults.timeout=5000

axios.interceptors.request.use(function(config) {
  // 请求之前判断并添加到pending
  config.cancelToken = new CancelToken(c => {
    removePending(config, c)
  })
  return config
},function (error) {
  return Promise.reject(error)
})

/*对响应拦截*/
axios.interceptors.response.use(function (response) {
    const res=response.data
    // 请求回来后删除pending存储
    removePending(response.config)
    if(response.status !== 200){
      return Promise.reject(res)
    }else{
      return res;
    }
  }, function (error) {
    // 请求回来后删除pending存储
    error.config && removePending(error.config)
    return Promise.reject(error);
  });

方法二:取消上一次请求参考open in new window

axios取消生意tabs中未返回的请求

在一个带有tabs的页面中:
tabs
如果我们点击"5万以下",此时出发加载数据,当页面数据未返回的时候,又点击了"5-10万",此时会再次去请求数据,如果"5万以下"的数据返回的比较慢,可能会将"5-10万"返回的数据给顶掉,此时页面显示的数据虽然tags在"5-10万",但是其实显示的是上一个标签的数据;所以我们应该在切换标签的时候,将当前标签未返回的请求取消掉来防止这种混乱的事情发生;在vue模版页面中:

export default {
  data() {
    return {
      list: null,
      cancel: null
    }
  },
  create() {
    this.getLists()
  }
  methods: {
    // 获取数据
    getLists() {
      const CancelToken = this.axios.CancelToken
      this.axios.get('/api',{
        cancelToken: new CancelToken(c => {
            // 调用c就可以取消此请求
            this.cancel = c
          })
      }).then(result => {
        this.lists = result.data
      })
    },
    // 每次切换标签时先调用此函数,就可以取消请求
    cancelAxios() {
      this.cancel()
    },
    changeTabs() {
      this.cancelAxios()
      this.getLists()
    }
  },
}

axios源码实现

源码路径:axios/lib/cancel/CancelToken.js

var Cancel = require('./Cancel');

function CancelToken(executor) {
  if (typeof executor !== 'function') {
    throw new TypeError('executor must be a function.');
  }
  // 将new Promise里面的reslove付值给外部的resolvePromise,可以方便在外面控制promise内部的状态改变
  var resolvePromise;
  this.promise = new Promise(function promiseExecutor(resolve) {
    resolvePromise = resolve;
  });

  var token = this;
  //上例中new CancelToken穿进去的c就是此处的cancel函数,调用c就相当于调用cancel函数
  executor(function cancel(message) {
    if (token.reason) {
      return;
    }

    token.reason = new Cancel(message);
    // 更改promise的状态,状态改变后会执行下面的then方法
    resolvePromise(token.reason);
  });
}

CancelToken.prototype.throwIfRequested = function throwIfRequested() {
  if (this.reason) {
    throw this.reason;
  }
};


CancelToken.source = function source() {
  var cancel;
  var token = new CancelToken(function executor(c) {
    cancel = c;
  });
  return {
    token: token,
    cancel: cancel
  };
};

module.exports = CancelToken;

上接resolvePromise方法
地址: axios/lib/adapters/xhr.js

if (config.cancelToken) {
  // 上面执行完取消后resolvePromise,会触发下面的then方法
  // 取消请求
  config.cancelToken.promise.then(function onCanceled(cancel) {
    if (!request) {
      return;
    }

    request.abort();
    reject(cancel);
    // Clean up request
    request = null;
  });
}