I am throwing an ajax call that downloads a few images.
At the same time, I need another loop that has to check if all the images have been downloaded (I know how many will be downloaded). I do it this way:
function check_download(){
ajax_call...
success: function(amount){if(amount < 40) check_download()}
}
call download_images(); // this starts the process of downloading images
call check_download();
So I launch the download and I send an ajax call to check if it has downloaded the 40 images. If not, then I want to launch another ajax call to check again, and so on.
But it only throws 2 ajax calls. The second one gets frozen and it does not return any value, so no loop is being done and I cannot check the progress of the download.
Any idea on how to launch several ajax calls to achieve this?
Related
Dependent on a selection, made on a website, plots are generated on a server where Flask runs.
The issue that I have is that generating e.g. 10 different plots can take up to 30s. What I like to achieve is to start updating the website as soon as the first plot is ready and then load automatically the others as soon as they are ready.
Currently, the following AJAX function is executed as soon as the user hits the "process" button on the website:
$.ajax({
type: "POST",
url: "/single",
data: { athleteName1: $('#athleteName1').val(), style: $('#style').val()},
success: function (results) {
$('#results').empty().append(results);
$('#results').show();
$('#submitbutton').prop('disabled', false);
},
error: function (error) {
console.log(error);
}
});
On the server site, plots are created and embedded in div-containers. They are subsequently concatenated an returned to the website at once as "diagStr":
#app.route('/single', methods=['POST', 'GET'])
def single():
loop 10 times:
diagStr += generate_plot()
return Markup(diagStr)
Doing it with "Streaming Contents" can only be part of the solution as AJAX waits until the the entire response is received.
Any idea how this is solved with today's technology?
There are multiple way you could achieve this, but some simple examples:
do your looping on the client side, and generate 10 separate Ajax requests, updating the web page when each response is received.
if you don't know in advance on the client side, how many loops you will have, then use a single request and have the server send the response as soon as the first loop is complete, along with a flag indicating whether there are more loops or not - the client can look at this flag and create a new Ajax request if there are more loops.
I have a function that performs a backup every 5 seconds. From time to time the target server of the backup is not reachable and the request stops until the timeout is reached.
Since this affects the user interface I execute this 'backup function' as a async ajax request.
setInterval("doSync()", 5000 );
function doSync() {
$.ajax({
url: "backup.php",
async : true
});
};
This runs pretty good in the background.
But as soon as a reload of the page is executed, already waiting backup function calls will be completed. So in the worst case, if I have a backup with 30 seconds timeout, the user has to wait this 30 seconds before the new page is loaded.
That is not acceptable for the user.
Which strategy can I implement to avoid this?
It would be ok to terminate the backup request...
I think that issue is rather specific to the browser.
Indeed, most of them limit the number of parallel requests to the same host and that's why it "waits" before reloading the page.
If you're calling the exact same URL via your AJAX request as the one you're trying to reload, Firefox will not run more than ONE request at the same time. A simple workaround is to append a random query string to the URL.
Another option is to use the javascript beforeunload event to cancel your AJAX request : Abort Ajax requests using jQuery
I would maybe think about setting timeout in your case.
I also found similar problem already solved: click
I have a function, that uses ajax, that takes really long to complete.
The thing is that I have a lot of files on server, that need to be processed, and the page I'm trying to make is like a status page.
It has a link to start processing, and file counts. It looks like this:
Click here to start process
files 0/500
When I click the link, it runs this function:
function generate_book_link_clicked(){
$.getJSON("/generate_book", function(data){
if (data['last'] == 'true'){
$('#done').fadeIn(200);
}else{
$('#current_count').html(parseInt($('#current_count').text())+1);
$('#generate_book_link').click();
}
});
}
This is the link code:
click me
and this is the code for the counter html (the "<%= #isbn_count.to_s %>" just returns the count):
<span id="current_count">0</span>/<span id="total_count"><%= #isbn_count.to_s %></span>
But what happens is, when ajax completes, it doesn't start the process over again, but the count just starts rapidly adding without ajax calls.
It's like, the first finishes successfully, but then it just starts rapidly adding values to "current_count", and it goes like that forever even over the original count (1000/500)..
I can't figure how to start the process again, currently.
I hope I made everything clear and that someone will be able to help me.
Instead of
$('#generate_book_link').click();
just call your function directly:
generate_book_link_clicked();
It's Google Chrome extension development. I'm using content script to inject into webpages. However some webpages have their own ajax scripts that change the content dynamically. How do I wait until such scripts are completed, since before their completion my script cannot obtain the correct content?
For example,
1- on Google search result page,
2- I want to append "text" to title of every search result item, which could be easily done by calling,
$('h3').append("text");
3- then listen to the search query change, done by
$('input[name="q"]').change( function(eventObj){
console.log("query changed");
// DOESN'T work
$('h3').append("text");
});
The last line doesn't work probably because at the time it's executed the page is still refreshing and $('h3') is not available. Google uses ajax to refresh the search result when the query is changed on the page.
So the question is how to capture this change and still be able to append "text" every time successfully?
EDIT:
Have tried and didn't work either:
$('h3[class="r"]').delay(1000).append("text");
and using .delay() is not really preferred.
EDIT:
.delay() is simply not designed to solve pause the execution of scripts other than UI effects. An workaround is
$('input[name="q"]').change(function(eventObj) {
setTimeout(function() {
$('h3[class="r"]').append(" text");
}, 1000);
});
But as I argued before, setTimeout() is connection-speed dependent, not preferred because I have to manually balance the time of waiting and the speed of response (of my script).
Although this post is down-voted for god-knows-why I'll still be waiting for an elegant answer.
Maybe with jQuery 1.7+ (or with older version using "live" or "delegate")
$('form').on( "change", 'input[name="q"]', function(eventObj){
console.log("query changed");
$('h3').append("text");
});
If form is another element, change it accordingly.
Both QWebFrame and QWebPage have void loadFinished(bool ok) signal which can be used to detect when a web page is completely loaded. The problem is when a web page has some content loaded asynchronously (ajax). How to know when the page is completely loaded in this case?
I haven't actually done this, but I think you may be able to achieve your solution using QNetworkAccessManager.
You can get the QNetworkAccessManager from your QWebPage using the networkAccessManager() function. QNetworkAccessManager has a signal finished ( QNetworkReply * reply ) which is fired whenever a file is requested by the QWebPage instance.
The finished signal gives you a QNetworkReply instance, from which you can get a copy of the original request made, in order to identify the request.
So, create a slot to attach to the finished signal, use the passed-in QNetworkReply's methods to figure out which file has just finished downloading and if it's your Ajax request, do whatever processing you need to do.
My only caveat is that I've never done this before, so I'm not 100% sure that it would work.
Another alternative might be to use QWebFrame's methods to insert objects into the page's object model and also insert some JavaScript which then notifies your object when the Ajax request is complete. This is a slightly hackier way of doing it, but should definitely work.
EDIT:
The second option seems better to me. The workflow is as follows:
Attach a slot to the QWebFrame::javascriptWindowObjectCleared() signal. At this point, call QWebFrame::evaluateJavascript() to add code similar to the following:
window.onload = function() { // page has fully loaded }
Put whatever code you need in that function. You might want to add a QObject to the page via QWebFrame::addToJavaScriptWindowObject() and then call a function on that object. This code will only execute when the page is fully loaded.
Hopefully this answers the question!
To check the load of specific element you can use a QTimer. Something like this in python:
#pyqtSlot()
def on_webView_loadFinished(self):
self.tObject = QTimer()
self.tObject.setInterval(1000)
self.tObject.setSingleShot(True)
self.tObject.timeout.connect(self.on_tObject_timeout)
self.tObject.start()
#pyqtSlot()
def on_tObject_timeout(self):
dElement = self.webView.page().currentFrame().documentElement()
element = dElement.findFirst("css selector")
if element.isNull():
self.tObject.start()
else:
print "Page loaded"
When your initial html/images/etc finishes loading, that's it. It is completely loaded. This fact doesn't change if you then decide to use some javascript to get some extra data, page views or whatever after the fact.
That said, what I suspect you want to do here is expose a QtScript object/interface to your view that you can invoke from your page's script, effectively providing a "callback" into your C++ once you've decided (from the page script) that you've have "completely loaded".
Hope this helps give you a direction to try...
The OP thought it was due to delayed AJAX requests but there also could be another reason that also explains why a very short time delay fixes the problem. There is a bug that causes the described behaviour:
https://bugreports.qt-project.org/browse/QTBUG-37377
To work around this problem the loadingFinished() signal must be connected using queued connection.