可以使用 xhrFields 将 onprogress 功能添加到 jQuery.ajax() 吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15668339/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can onprogress functionality be added to jQuery.ajax() by using xhrFields?
提问by dcorsello
As suggested here: https://gist.github.com/HenrikJoreteg/2502497, I'm trying to add onprogress functionality to my jQuery.ajax()
file upload. The upload works fine, and the onprogress event is firing, but not as I expected--instead of firing repeatedly at some time interval, it's firing only once, when the upload has completed. Is there a way to specify the frequency of onprogress refreshes? Or, am I trying to do something that can't be done? Here's my code:
正如此处所建议的:https: //gist.github.com/HenrikJoreteg/2502497,我正在尝试将 onprogress 功能添加到我的jQuery.ajax()
文件上传中。上传工作正常,并且 onprogress 事件正在触发,但不像我预期的那样 - 而不是在某个时间间隔重复触发,它只触发一次,当上传完成时。有没有办法指定 onprogress 刷新的频率?或者,我是否正在尝试做一些无法完成的事情?这是我的代码:
$.ajax(
{
async: true,
contentType: file.type,
data: file,
dataType: 'xml',
processData: false,
success: function(xml)
{
// Do stuff with the returned xml
},
type: 'post',
url: '/fileuploader/' + file.name,
xhrFields:
{
onprogress: function(progress)
{
var percentage = Math.floor((progress.total / progress.totalSize) * 100);
console.log('progress', percentage);
if (percentage === 100)
{
console.log('DONE!');
}
}
}
});
回答by GetFree
Short answer:
No, you can't do what you want using xhrFields
.
简短回答:
不,您不能使用xhrFields
.
Long answer:
长答案:
There are two progress events in a XmlHttpRequest object:
XmlHttpRequest 对象中有两个进度事件:
The response progress(
XmlHttpRequest.onprogress
)
This is when the browser is downloading the data from the server.The request progress(
XmlHttpRequest.upload.onprogress
)
This is when the browser is sending the data to the server (including POST parameters, cookies, and files)
响应进度(
XmlHttpRequest.onprogress
)
这是浏览器从服务器下载数据的时间。请求进度(
XmlHttpRequest.upload.onprogress
)
这是浏览器向服务器发送数据(包括 POST 参数、cookie 和文件)的时间
In your code you are using the response progress event, but what you need is the request progress event. This is how you do it:
在您的代码中,您使用的是响应进度事件,但您需要的是请求进度事件。这是你如何做到的:
$.ajax({
async: true,
contentType: file.type,
data: file,
dataType: 'xml',
processData: false,
success: function(xml){
// Do stuff with the returned xml
},
type: 'post',
url: '/fileuploader/' + file.name,
xhr: function(){
// get the native XmlHttpRequest object
var xhr = $.ajaxSettings.xhr() ;
// set the onprogress event handler
xhr.upload.onprogress = function(evt){ console.log('progress', evt.loaded/evt.total*100) } ;
// set the onload event handler
xhr.upload.onload = function(){ console.log('DONE!') } ;
// return the customized object
return xhr ;
}
});
The xhr
option parameter must be a function that returns a native XmlHttpRequest object for jQuery to use.
该xhr
选项的参数必须是jQuery的返回原生XMLHttpRequest对象使用的功能。
回答by CooCooCaCha
You need to add an event handler to the request itself before it is sent out. jQuery.ajax allows this through the 'beforeSend' property http://api.jquery.com/jQuery.ajax/
在发出请求之前,您需要向请求本身添加一个事件处理程序。jQuery.ajax 通过 'beforeSend' 属性允许这样做http://api.jquery.com/jQuery.ajax/
for example: http://www.dave-bond.com/blog/2010/01/JQuery-ajax-progress-HMTL5/
例如:http: //www.dave-bond.com/blog/2010/01/JQuery-ajax-progress-HMTL5/
* EDIT * Make sure to look at the second code sample of that example link. I believe the first one is out of date with modern versions of jQuery.
* 编辑 * 确保查看该示例链接的第二个代码示例。我相信第一个对于现代版本的 jQuery 来说已经过时了。
$.ajax({
xhr: function()
{
var xhr = new window.XMLHttpRequest();
//Upload progress
xhr.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
//Do something with upload progress
console.log(percentComplete);
}
}, false);
//Download progress
xhr.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
//Do something with download progress
console.log(percentComplete);
}
}, false);
return xhr;
},
type: 'POST',
url: "/",
data: {},
success: function(data){
//Do something success-ish
}
});
回答by Andrew Foster
This is a bit of a hack of another answer elsewhere on Stack Overflow, but I think answers your question. I have doctored it to my own needs of pumping "streamed" data from the server to a scrollable div (which I can then force to always scroll to the bottom thus showing progress over time and thus not waiting for the entire record set to complete).
这是 Stack Overflow 上其他地方的另一个答案,但我认为可以回答您的问题。我已经根据自己的需要修改了它,将“流式”数据从服务器泵送到可滚动的 div(然后我可以强制始终滚动到底部,从而随着时间的推移显示进度,从而不等待整个记录集完成) .
The client sidecode below adds the resulting content to a predefined div with id "scrollable_area" (which can then be scrolled)...
下面的客户端代码将生成的内容添加到 id 为“scrollable_area”的预定义 div(然后可以滚动)...
<div style="position:absolute; left:5px; right:5px; top:5px; height:35px;">
<label for="auto_scroll">Auto Scroll</label> <input type="checkbox" id="auto_scroll" checked>
</div>
<div id="scrollable_area" style="position:absolute; overflow:auto; left:5px; right:5px; top:45px; bottom:5px;"></div>
<script type="text/javascript">
var last_response_len = false;
var auto_scroll = null;
var scrollable_area = null;
$().ready(function() {
auto_scroll = document.getElementById("auto_scroll");
scrollable_area = document.getElementById("scrollable_area");
$.ajax("your_api_call.php", {
xhrFields: {
onprogress: function(e) {
var this_response, response = e.currentTarget.response;
if(last_response_len === false) {
this_response = response;
last_response_len = response.length;
} else {
this_response = response.substring(last_response_len);
last_response_len = response.length;
}
scrollable_area.innerHTML += this_response;
if(auto_scroll.checked) {
scrollable_area.scrollTop = scrollable_area.clientHeight + scrollable_area.scrollHeight + 500;
}
}
}
})
.done(function(data) {
console.log("Completed response");
})
.fail(function(data) {
console.log("Error: ", data);
});
console.log("your_api_call.php Request Sent!");
});
</script>
The server side"your_api_call.php" file call would need to then flush its output (per data row so as to see progress over time) which can then be displayed immediately within the above "scrollable_area" div...
在服务器端“your_api_call.php”文件调用需要再刷新其输出然后可以立即上面的“scrollable_area”专区内显示(每个数据行,以便查看一段时间进度)...
// Do Db loop
while ($record = $recordset->fetch(PDO::FETCH_ASSOC)) {
set_time_limit(10); // Don't timeout on large data sets seeing as this is a big task that we are wanting to watch progress!
echo 'Do what you gotta do... ' . $record["register_id"] . '<br>';
flush(); // Push to the client / ajax
ob_flush(); // As above
}
Short answer... YES. Hope this helps :-)
简短的回答......是的。希望这可以帮助 :-)