中止 xmlhttprequest
Posted
技术标签:
【中文标题】中止 xmlhttprequest【英文标题】:Aborting the xmlhttprequest 【发布时间】:2011-12-17 22:04:54 【问题描述】:我正在使用 html5 上传文件。我有一个按钮单击事件附加到函数uploadFile()
。它工作正常。我还有一个单独的按钮来取消上传。我知道我们需要调用xhr.abort()
,但是如何访问uploadCanceled
函数中的xhr 对象?我可以使 xhr 对象成为全局对象,但这不是正确的方法。有人可以在这里指导我吗?
function uploadFile()
var filesToBeUploaded = document.getElementById("fileControl");
var file = filesToBeUploaded.files[0];
var xhr= new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadFailed, false);
xhr.addEventListener("abort", uploadCanceled, false);
xhr.open("POST", "upload.php", true);
var fd = new FormData();
fd.append("fileToUpload", file);
xhr.send(fd);
function uploadCanceled(evt)
alert("Upload has been cancelled");
干杯
【问题讨论】:
您是在xhr
被中止后尝试访问它(在uploadCanceled
内),还是需要访问它以便致电abort
?您的问题和下面的 cmets 似乎并不一致。
【参考方案1】:
addEventListener
会将uploadCanceled
的上下文(this
)设置为xhr
:
function uploadCanceled(evt)
console.log("Cancelled: " + this.status);
示例:http://jsfiddle.net/wJt8A/
如果您需要通过“取消”点击触发xhr.abort
,则可以返回一个引用并在此之后添加您需要的任何侦听器:
function uploadFile()
/* snip */
xhr.send(fd);
return xhr;
document.getElementById('submit').addEventListener('click', function ()
var xhr = uploadFile(),
submit = this,
cancel = document.getElementById('cancel');
function detach()
// remove listeners after they become irrelevant
submit.removeEventListener('click', canceling, false);
cancel.removeEventListener('click', canceling, false);
function canceling()
detach();
xhr.abort();
// detach handlers if XHR finishes first
xhr.addEventListener('load', detach, false);
// cancel if "Submit" is clicked again before XHR finishes
submit.addEventListener('click', canceling, false);
// and, of course, cancel if "Cancel" is clicked
cancel.addEventListener('click', canceling, false);
, false);
示例:http://jsfiddle.net/rC63r/1/
【讨论】:
感谢您的回复。这帮助很大。 @moderns 不完全是。 IE7 支持此答案的重点xhr.status
和xhr.abort()
。但是,addEventListener()
仅受 IE9 及更高版本支持。以前的版本改为使用attachEvent()
。 "Correct usage of addEventListener() / attachEvent()?" 另外,问题中的FormData
需要IE 10 and later。
@JonathanLonowski 非常感谢!
@moderns 无需打扰:直接使用onclick
和onload
。【参考方案2】:
您应该能够在您的 cancelledUpload 事件处理程序中引用“this”关键字。那是指 XMLHttpRequest。将其放入处理程序中:
this.abort();
【讨论】:
感谢您的回复。但是如何在按钮的帮助下调用 uploadCanceled 函数呢?我知道如果我重新加载页面会调用它。我不认为我可以将它与 onClick 事件相关联,然后使用 this.abort() 对吗? 看看这个:jsfiddle.net/yE8r3 代码不会在这里运行,而是展示如何将东西包装在一个闭包中。名为 s 的对象在闭包和点击处理程序中可见,但在闭包之外不可见。 什么是canceledUpload
事件处理程序?
对不起,应该说“uploadCanceled”,是原发帖人创建的函数名。【参考方案3】:
中止所有 XMLHttpRequest:
var array_xhr = new Array();
function uploadFile()
...
var xhr = new XMLHttpRequest();
array_xhr.push(xhr);
...
function abort_all_xhr()
if (array_xhr.length>0)
for(var i=0; i<array_xhr.length; i++)
array_xhr[i].abort();
array_xhr.length = 0;
;
abort_all_xhr();
【讨论】:
如果没有必要,无论如何都要检查该条件。设置 .length 似乎不太好。您可以将它们一一弹出或将数组分配给[]【参考方案4】:您可以使用AbortController 和 fetch 来中止请求。
Demo
代码
const btn = document.getElementById('btn');
const btn2 = document.getElementById('btn2');
const url = 'https://www.mocky.io/v2/5185415ba171ea3a00704eed?mocky-delay=1000ms';
const ctrl;
btn.addEventListener('click', e =>
ctrl = new AbortController();
const signal = ctrl.signal;
fetch(url, signal )
.then(r => r.json())
.then(r =>
console.log('Request result', r);
).catch(e =>
console.error('Request was aborted. Error:', e);
)
);
btn2.addEventListener('click', e =>
ctrl.abort();
);
【讨论】:
请注意,我们的好朋友 IE 不支持它。 developer.mozilla.org/en-US/docs/Web/API/…以上是关于中止 xmlhttprequest的主要内容,如果未能解决你的问题,请参考以下文章
可以像中止一个Thread(Thread.Abort方法)一样中止一个Task吗?