JS uses axios to cancel the request-Kaiqisan

JS uses axios to cancel the request

Yahharoo, Kaiqisan Suu, one ordinary student programmer, this is a controversial issue.

This time there is a lot of content. If you just want to copy the code, I will make a directory and just jump to the directory to find the code.


The front end unilaterally defaults to cancel the request, so the code here only matters for the front end.

Cancellation method written on the official website

/* a.js */
import axios from 'axios'

let CancelToken = axios.CancelToken
let source = CancelToken.source()


export default {
    
    
    getReq() {
    
    
        axios({
    
    
            methods: 'get',
            url: 'http://localhost:3000/testGet', 
            // 本地写了简易服务器,设置延时处理请求模拟网卡的情况,大家有能力的可以自己写一个服务器
            cancelToken: source.token	// 关键代码
        }).then(res => {
    
    
            console.log(res)
        }).catch(err => {
    
    
            console.log(err)
        })
    },

    cancelReq() {
    
    
        source.cancel('do cancel')
        source = CancelToken.source()	// 重新规划
    }
}

These codes can also be directly downloaded into the .vue.jsx file, as long as the parameters are in place and the appropriate opportunity is found to trigger it.

PS: The above cancellation operation is affected by AOE, which means that it can cancel multiple requests at once. If one person initiates multiple requests in a short period of time, the backend has not had time to process it, and unprocessed requests line up. One cancel operation can cancel all unreturned requests.

///

Now let's take a look at its source code, what is the process of Kangkang like! ?

CancelToken = axios.CancelToken 

First of all, to study this sentence.

We open the source code in the output bar and see the following

function CancelToken(executor) {
    
    
  if (typeof executor !== 'function') {
    
    		// 非法情况处理
    throw new TypeError('executor must be a function.');
  }

  var resolvePromise;
  this.promise = new Promise(function promiseExecutor(resolve) {
    
    
    resolvePromise = resolve;		// 通过外部来影响这个异步函数的去向
  });

  var token = this;
  executor(function cancel(message) {
    
    
    if (token.reason) {
    
    		// 如果已经取消了,就不再执行第二次'取消请求'
      return;
    }

    token.reason = new Cancel(message);
    resolvePromise(token.reason); // 成功取消请求,返回参数reason
  });
}

/**
 * Throws a `Cancel` if cancellation has been requested.
 */
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
    
    
  if (this.reason) {
    
    	
    throw this.reason;	// 
  }
};

/**
 * Returns an object that contains a new `CancelToken` and a function that, when called,
 * cancels the `CancelToken`.
 */
CancelToken.source = function source() {
    
    
  var cancel;
  var token = new CancelToken(function executor(c) {
    
    
    cancel = c;
  });
  return {
    
    
    token: token,
    cancel: cancel
  };
};

module.exports = CancelToken;

Then there is the second sentence, source = CancelToken.source()which is for the last function of the above source code. By printing, we can see that this CancelToken.source()returns an object. It has two members, one is the token asynchronous function (prototype is Promise), and the other is the cancel method. .

Then the basic naming is OK, and then it can be officially put into use.

After the cancel() method is triggered in the request, this method is executed (go to the source code above to find it yourself)

function cancel(message) {
    
    
    if (token.reason) {
    
    		// 如果已经取消了,就不再执行第二次'取消请求'
      return;
    }

    token.reason = new Cancel(message);
    resolvePromise(token.reason); // 成功取消请求,返回参数reason
}

Then trigger resolvePromise and take the then route

if (config.cancelToken) {
    
     // 检测原生的请求里是否有cancelToken,如果没有就不执行下面的方法
	config.cancelToken.promise.then(function onCanceled(cancel) {
    
    
		if (!request) {
    
    		// 没有请求直接劝退
			return;
		}
		request.abort();	// 原生的取消请求方法
		reject(cancel);		// 请求那边走catch路线,返回cancel参数
    	// 复位数据
		request = null;		// 清空请求
	});
}

As for CancelToken.source()the problem of calling reset again after canceling the request , if it is not reset, the next request will be cancelled directly, because the CancelToken voucher has been triggered at this time. If you want to verify, you can check before and after the request is cancelled CancelToken.source(). We will It was found that after the request was cancelled, there was an additional reason attribute in its token parameter. This means that the request has been cancelled. The voucher is one-time. If it is found that the voucher has a reason attribute, it means that the request needs to be cancelled. So it needs to be reset.

Cancellation method 2

The principle has been explained above, and I will not expand it in detail below

/* a.js */
import axios from 'axios'

let CancelToken = axios.CancelToken
let cancel		// 取消参数


export default {
    
    
    getReq() {
    
    
        axios({
    
    
            methods: 'get',
            url: 'http://localhost:3000/testGet', 
            // 本地写了简易服务器,设置延时处理请求模拟网卡的情况,大家有能力的可以自己写一个服务器
            cancelToken: new CancelToken(function executor(c) {
    
     
    			cancel = c;
  			}) // 等同于上面的 source.token
        }).then(res => {
    
    
            console.log(res)
        }).catch(err => {
    
    
            console.log(err)
        })
    },

    cancelReq() {
    
    
        cancel('do cancel')
    }
}

PS: The parameter c in the executor function is a function

function cancel(message) {
    
    
    if (token.reason) {
    
    		// 如果已经取消了,就不再执行第二次'取消请求'
      return;
    }

    token.reason = new Cancel(message);
    resolvePromise(token.reason); // 成功取消请求,返回参数reason
}

It can only intercept the current request, not all the requests that have been sent, so please do anti-skid operations when developing !

More highly encapsulated, use the cancellation method after axios.create

/* 配置文件 */
import axios from 'axios'

// 创建axios实例
const service = axios.create({
    
    
    baseURL: configJS.BASE_API,
})


// request拦截器
service.interceptors.request.use(
    ...........// 请求拦截
)

// respone拦截器
service.interceptors.response.use(
    ............
)

export default service

The configuration file is created normally

/* api仓库 */
import axios from 'axios'
import request from '@/utils/request'	// axios配置文件

getInfo(data, that) {
    
    
    return request({
    
    
        url: 'xxxxxxxx', // 自己定
        method: 'get',	// 只适合get请求的取消
        params: data,	// 参数
        cancelToken: new axios.CancelToken(function executor(c) {
    
    
            that.source = c
        })
    })
},
/* 开始正式调用 */

exeGetInfo() {
    
    
    api.getInfo({
    
     id: 10 }, this).then(res => {
    
    
		.........
	}).catch(err => {
    
    
	   	........
	})
}

cancelQuest() {
    
    
    if (typeof this.source === 'function') {
    
    
        this.source('终止请求') //取消请求
    }
},

Later, I was thinking about the principle of this interrupt request. I thought it was the front end sending a rejection request to the back end again. However, after opening the server, I found that I did not receive the second request again when I cancelled the request. , So I suspect that the front-end directly rejected the request sent by the back-end.

Below is my backend node.js code

/* index.js主入口文件 */

const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const cors = require('cors');


let router = require('./routes/routers')


app.all('*', function(req, res, next) {
    
    
	console.log(req.method);
	res.header("Access-Control-Allow-Origin", "*");
	res.header('Access-Control-Allow-Headers', 'Content-type');
	res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS,PATCH");
	res.header('Access-Control-Max-Age', 1728000); //预请求缓存20天
	next();
});
app.use(cors({
    
    
	origin: ['http://localhost:8800'],
	methods: ['GET', 'POST'],
	allowHeader: ['Content-Type', 'Authorization']
}))
app.use(bodyParser.urlencoded({
    
    
	extended: false
}))
app.use(bodyParser.json())

app.use(router)

app.listen(3000, () => {
    
    
	console.log('服务器启动')
})
/* routers.js路由文件 */

const express = require('express')
const router = express.Router()

router.get('/testGet', (req, res) => {
    
    
    setTimeout(() => {
    
     // 增加处理时间,便于测试setTimeout
        console.log('gggggggggggggg');
        res.json([		// 返回的信息
            {
    
    
                name: 'Kaiqisan',uid: 100
            },
            {
    
    
                name: 'Tom',uid: 101
            }
        ])
    }, 3000)
})

module.exports = router

Later, I found out that even if I canceled the request, the backend would still send information to the frontend, that is to say, what was sent from the backend after the frontend rejected it, and I would just discard it. In the axios method, go directly to the catch route, report the error, and the method is over. Therefore, by analogy, this method can only cancel the get request , but not the post and other requests that require the back-end to modify the background data, unless the back-end is required to cancel the related operation again when the cancel operation is triggered.

to sum up

Canceling requests is a very important method. Although it will not reduce the burden on the backend (server: I thank you!), it can significantly reduce the memory consumption of the frontend. Fewer requests means less data capture, and means less The useless data rendering and assignment will also moderately reduce the complexity of front-end project engineering, coupled with anti-skid lock, perfect!

Guess you like

Origin blog.csdn.net/qq_33933205/article/details/108127541