Reputation: 28853
I have the following JS to retrieve some JSON data from a controller method in a Rails app:
$.ajax({
xhr: function() {
var xhr = $.ajaxSettings.xhr();
xhr.onprogress = function(e) {
if (e.lengthComputable) {
console.log(e.loaded / e.total);
}
};
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
console.log(e.loaded / e.total);
}
};
return xhr;
},
cache: false,
url: '/get_data',
method: 'GET',
dataType: 'JSON',
success: function(data) {
console.log(data);
}
});
And the method is as follows:
def get_data
@data = [{....}]
respond_to do |format|
format.html
format.json do
response.headers['Content-Length'] = @data.to_s.length.to_s
render json: @data
end
end
end
The method can take up to 3-4 seconds to return due to the @data
being either large or requiring complex calculations first, so I want to show a progress bar whilst the AJAX is taking place.
Note: I don't just want to show a loader that shows before and after the AJAX, but actually show the progress!
However I'm finding that lengthComputable
is always false...
How can I get Rails to send back the correct progress? I've added the Content-Length
header but it never shows up in the response...
Upvotes: 2
Views: 1301
Reputation: 537
I was wrong. It's not a real progress Bar, but the idea was this:
$(function() {
var pg = 0;
function progressbarAdd(){
pg++;
$('#bar').progressbar('option', 'value', pg).children('.ui-progressbar-value').css('display', 'block');
}
$('#bar').progressbar({ value: 0 });
$(document).on({
ajaxStart: function(){
timer = setInterval(function(){
progressbarAdd()
}, 100);
},
ajaxStop: function(){
clearTimeout(timer);
$('#bar').progressbar('option', 'value', 100);
}
});
$.ajax({
method: 'GET',
url:'https://viacep.com.br/ws/01001000/json/',
dataType: 'json',
success: function() {
console.log('JSON:', arguments[0]);
},
error: function() {
console.log('Fail');
}
});
});
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/black-tie/jquery-ui.css" />
</head>
<body>
<div id="bar"></div>
</body>
</html>
Upvotes: 1
Reputation: 537
Use jQuery to know when the request has finished.
$(document).on({
ajaxStart: function(){
//show or create the progress bar
},
ajaxStop: function(){
//hide or remove the progress bar
}
});
Upvotes: 0
Reputation: 37975
The ProgressEvent.lengthComputable read-only property is a Boolean flag indicating if the resource concerned by the ProgressEvent has a length that can be calculated.
Meaning it needs a content-length
header... to know how big the resource is. What you are probably doing is sending a application-octet stream with no know size
Upvotes: 0