ajax取消,Ajax取消相关的那些事

我们开发web页面时候,也许会遇到和异步请求取消相关的问题。

如:在一个请求发送之后,用户做了一个取消指令,为了节省资源,我们需要把已经被用户取消的请求终止掉;或者是一个页面正在用ajax请求后台,突然页面发生了跳转,而我们未完成的ajax莫名其妙地走进了error里面了。

为了解决这两问题,我们今天一起看看和异步请求取消相关的那些事。

Ajax的取消

当我们创建一个XMLHttpRequest对象的时候,我们就会发现两个api——abort和onabort,这就是终止异步请求的方法与其响应事件。

执行完abort之后,浏览器和被请求的服务器都会发生什么呢?

MDN的解释非常的简单,就是中断已发送的请求。这个请求指的是http请求,而不是tcp连接,这样就会出现一个问题,基于http请求原理,当一个请求从客户端发出去之后,服务器端收到请求后,一个请求过程就结束了,这时就算是客户端abort这个请求,服务器端仍会做出完整的响应,只是这个响应客户端不会接收罢了。

所以这个abort是仅给客户端使用的,不能作为供服务器端判断请求是否继续执行的依据。

那么被abort的请求对客户端有哪些影响呢?我们可以做一个实验。

var xhr = new XMLHttpRequest();

xhr.open("GET","#");

xhr.send();

xhr.onload = function(){

console.log("abort前");

console.log(xhr.readyState);

console.log(xhr.status);

xhr.abort();

console.log("abort后");

console.log(xhr.readyState);

console.log(xhr.status);

}

09c83d77e8a1fe2ec4b7e1f9b0bf92f7.png

我们可以看到readyState和status在abort之后被重置回0。

那么我们能用这两个参数作为判断请求被abort的依据吗?

首先能够让status等于0的情况太多了,如请求本地资源、网络不可用、请求超时,这些都可以让status被置0;readyState等于0能否作为请求是否被abort了还不好说,需要进一步判断,readyState等于0相当于请求未初始化,请求都已经send了readyState却等于0,笔者认为是可以作为abort的判断依据的,但是无法完全证明。

有没有更可靠的证明请求是否执行了abort方法呢?有,答案是使用onabort,onabort作为abort的响应函数,是最直接有效的判断abort手段。

页面跳转时候ajax会自动“abort”

笔者从前认为abort离我很远,但是在实际项目中,笔者发现页面我开发的请求经常被abort。这个abort动作当然不是我发起的,也不是用户发起的,他是浏览器自动发起的。笔者发现一个页面跳转的时候,浏览器会自动把所有响应未完成的请求执行“abort”,而响应已完成的请求则不会这样。我们可以做一个实验

//要在chrome或者webkit内核上运行

var xhr = new XMLHttpRequest();

//访问一个不存在的地址 取保请求不会马上响应

xhr.open("GET","http://aaa.bbbbbbbb.com");

xhr.send();

xhr.onabort = function(){

console.log(xhr.readyState);

console.log(xhr.status);

alert("执行onabort");

};

setTimeout(function(){

//模拟跳转页面

location.href = "http://www.baidu.com"

},0);

结果网页上弹出了一个alert,显示着"执行onabort"。

79ad63dd389c77b94b2bc0cec7cf121d.png

再看控制台,我们会发现status不变还是0,而readyState却是4,这也是浏览器发出的abort和手动执行abort最大不同。

以上测试仅在chrome上有效,ie、edge、火狐在页面跳转的时候,不会触发未完成的请求的onabort事件,但是会触发onreadystatechange事件。不管怎么讲,当页面发生跳转的时候,浏览器可能会“abort”我们的异步请求。

jQuery对abort的处理

jquery又是如何对abort封装的呢?我们在使用(

用.ajax封装的方法,如、.post)的时候,会返回一个xhr对象,这个基于$.deferred.promise封装的jquery自己的对象,而不是原始的XMLHttpRequest或者ie的ActiveXObject对象。在这个对象中定义了如abort等方法,使得开发者可以手动abort一个ajax请求。

var xhr = $.ajax(url);

xhr.abort();

另外,jquery的超时也是通过setTimeout和abort实现的,所以当你使用jquery发出的请求超时的时候,实际上是被jquery把请求abort了。如何区分jquery的超时和手动abort呢?方法就是靠stutusText,对于timeout和abort两个客户端做出的响应,jquery会给stutusText设定固定的值,abort的时候,stutusText的值为“abort”,超时的时候stutusText值是“timeout”。

fetch及promise如何取消与取消处理的

fetch作为ajax的升级版,越来越多的浏览器已经支持他了,那fetch又是如何取消异步请求的呢?答案是fetch暂时不能被取消...,因为没有对应的api。

Fetch 也有它的不足,相对于 XHR  来说,目前它具有以下劣势:

不能取消(虽然 AbortController 能实现,但是目前兼容性基本不能使用,可以使用 polyfill )

不能获取进度

不能设置超时(可以通过简单的封装来模拟实现)

兼容性目前比较差(可以使用 polyfill 间接使用 XHR 来优雅降级,这里推荐使用 isomorphic-fetch )

var oldFetchfn = fetch;

var controller = new AbortController();

var signal = controller.signal;

var downloadBtn = document.querySelector('.download');

var abortBtn = document.querySelector('.abort');

downloadBtn.addEventListener('click', fetchVideo);

abortBtn.addEventListener('click', function(){

controller.abort();

console.log('Download aborted');

});

function fetchVideo(){

...

fetch(url, {signal}).then(function(response){

...

}).catch(function(e){

reports.textContent = 'Download error: ' + e.message;

})

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值