赞
踩
目录
CancelToken存在内存泄露隐患【切片上传长时间没有中断】
观察订阅+
xhr.abort()
- 取值范围是 0 到 4,分别表示不同的状态:
- 0: 请求未初始化(
open
方法还未调用)。- 1: 服务器连接已建立(
open
方法已经调用)。- 2: 请求已接收(
send
方法已经调用,并且头部和状态已经可获得)。- 3: 请求处理中(响应体正在接收)。
- 4: 请求已完成,且响应已就绪。
- // 创建AbortController实例且存放到controller上
- // 注意这里每次请求都会创建一个新的AbortController实例,
- //是因为AbortController实例调用abort后
- //AbortController实例的状态signal就为aborted不能更改
- controller.current = new AbortController();
- const xhr = new XMLHttpRequest();
- xhr.open("get", "https://mdn.github.io/dom-examples/abort-api/sintel.mp4");
- xhr.onreadystatechange = () => {
- if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
- setMessage("下载成功");
- setLoading(false);
- }
- };
- // 监听AbortController实例的abort事件,当AbortController实例调用abort方法时,就会触发该事件执行回调
- controller.current.signal.addEventListener("abort", () => {
- setMessage("下载中止");
- setLoading(false);
- xhr.abort();
- });
- xhr.send();
- // 调用AbortController实例的abort方法,从而触发上面注册在abort事件的回调的执行
- const abortDownload = () => {
- controller.current.abort();
- };
CancelToken
- 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;
-
- this.promise.then(function (cancel) {
- if (!token._listeners) return;
-
- var i;
- var l = token._listeners.length;
- // 遍历执行所有注册的监听器
- for (i = 0; i < l; i++) {
- token._listeners[i](cancel);
- }
- // 清空监听器数组
- token._listeners = null;
- });
-
- // source.cancel指向此处的cancel函数
- //在取消时调用 resolvePromise 函数
- executor(function cancel(message) {
- // token.reason有值代表cancel已被执行,CancelToken是一个一次性的Subject,notify一次后即失效
- if (token.reason) {
- return;
- }
-
- token.reason = new CanceledError(message);
- // resolvePromise执行时,会执行上面this.promise.then中传入的回调函数。从而把listeners全执行
- resolvePromise(token.reason);
- });
- }
(un)subscribe
subscribe
注册onCancel
函数unsubscribe
注销onCancel
函数- CancelToken.prototype.subscribe = function subscribe(listener) {
- // 如果CancelToken实例已经执行cancel,直接执行该回调函数
- if (this.reason) {
- listener(this.reason);
- return;
- }
-
- // 如果CancelToken实例还没执行cancel,则把回调函数放进_listeners里
- if (this._listeners) {
- this._listeners.push(listener);
- } else {
- this._listeners = [listener];
- }
- };
-
- // 把回调函数从_listeners中移除
- CancelToken.prototype.unsubscribe = function unsubscribe(listener) {
- if (!this._listeners) {
- return;
- }
- var index = this._listeners.indexOf(listener);
- if (index !== -1) {
- this._listeners.splice(index, 1);
- }
- };
- CancelToken.source = function source() {
- var cancel;
- var token = new CancelToken(function executor(c) {
- cancel = c;
- });
- return {
- token: token,
- cancel: cancel,
- };
- };
- //初始化
- let cancel = null;
-
- //请求
- if(cancel != null) cancel() //如果上一次的请求还在继续,则取消
-
- axios({
- method:"get",
- url:"http://localhost:3000/test.php",
- cancelToken:new axios.CancelToken(function(c){
- cancel = c
- })
- }).then(response=>{
- //处理响应数据
- cancel = null
- }).catch(reason=>{
- //错误处理
- })
- }
- let source = axios.CancelToken.source();
-
- // 判断上一次的请求是否还在继续,如果还在继续,则取消上一次的请求
- if(source.token._listeners!=undefined )
- {
- source.cancel("取消请求")
- source = axios.CancelToken.source()
- }
- axios.get('http://localhost:3000/front-end/axios/response.php',{
- cancelToken:source.token
- }).then(response=>{
- // 处理响应
- }).catch(reason=>{
- if(axios.isCancel(reason)){
- console.log("取消请求",reason)
- }else{
- //错误处理
- }
- })
- }
-
2021 年 10 月推出的AxiosV0.22.0
版本中把CancelToken
打上 声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。