I have a script that runs a long conversion php script and a progress polling script. After looking at several posts about this subject i found that it should be possible to use async ajax calls combined with timeout from javascript to create a construction that would poll the progress regularly and update my page with a percentile number. See code below
function startExcelConversion(excelname){
var poll = function(){
setTimeout(function(){
$.ajax({
url: "../include/ajax/ajax.php?action=poll_progress",
success: function(data){
//Update the progress bar
// show progress
console.log('progresser: '+data);
$("#progress").val(data);
//Setup the next poll recursively
poll();
},
complete: function( jqXHR, textStatus ){
//Update the progress bar
// show progress
console.log(textStatus);
},
dataType: "json"
});
}, 3000);
};
poll();
//show loading image
console.log('starting conversion');
$('#progress').val("Excel openen...");
$('#main').prepend('<img id="loading" src="../include/image/load.gif">');
$("#loading").show();
$.ajax({
url: '../import/import_main.php?clean&action=importexcel&excelname='+excelname,
success: function(data) {
console.log(data);
$("#main").html(data)
$('#loading').hide();
}
});
return false;
}
the first block launches the script that runs a while (excel reading and conversion).This script updates a database table every 10 rows to set the progress. the second block (from start polling onwards0 should launch a php script that reads this progress db field and echo it so i can update my input field with the percentile. However the polling script is not called during the runtime of the first php script (import_main.php). I tried $.post and $.get calls (which should as $.ajax be asynchronous by default). Also tried setInterval but that did not work and was not recommended due to timing problems. Am i missing something obvious here or is it a setting in php i am missing?
thnx in advance
I would try to define poll at the top of the script, like:
var poll = function(){
setTimeout(function(){
$.ajax({
url: "../include/ajax/ajax.php?action=poll_progress",
success: function(data){
//Update the progress bar
// show progress
console.log('progresser: '+data);
$("#progress").val(data);
//Setup the next poll recursively
poll();
},
dataType: "json"
});
}, 3000);
});
and then call it, like, poll(), after the ajax call. See if that helps. Right now, you have an anonymous function after the ajax call, but it tries to call itself with poll(); in the success callback, which isn't going to be defined.
it turned out the problem was threefold:
The first problem was indeed the use of an IIFE function that was not defined at runtime. So using inline function such as z416175 described was certainly valid
The second problem was that when a session is active in PHP it will block other (ajax) calls to prevent session overwriting. So using session_write_close() before entering the long running script worked to allow asynchronous ajax calls for progress updating. See this post (thnx to z416175) One ajax call block other ajax call
The third problem was that when you use xdebug the second problem remains because xdebug keeps a session open preventing the asynchronous ajax progress update call. So be aware when testing that xdebug causes problems with this
Thanks for all input. I have credited z416175's post for various usefull info in his answer and comments
Related
I've looked into a great deal of solutions which make use of setInterval and setTimeout, however I thought I could give it a go adding a delay between function calls with use of a python script.
To explain the code:
I have a dropdown menu which contains the football matches being played today. When a user selects an option from this dropdown list i.e. it detects a change, then it executes a bunch of code to update the page with the relevant information.
Within this function I have another function liveCommentaryCall()
which uses AJAX to get the latest updates in the football match selected from the dropdown menu.
Of course I need to call this every X seconds to update the webpage
regarding the latest events.
At the end of the function I make an AJAX POST request to a
specific URL /delayRequest, which I then have that route in flask
simply perform a sleep()and return.
After this I then call the function liveCommentaryCall()again to
restart the update procedure.
JAVASCRIPT
$("#teamDropdownSelector").change(function(){
.
.
.
function liveCommentaryCall(){
alert("called");
.
. // bunch of code to update the page
.
$.ajax({
url: "/delayRequest",
type: "POST",
data: JSON.stringify(""),
success: function(response) {
alert("RESPONSE RECIEVED");
},
error: function(delayError) {
alert("Something's gone wrong!");
}
});
liveCommentaryCall();
}
//Now out of the function scope.
//Below is the first time the liveCommentaryCall function gets called.
liveCommentaryCall();
});
PYTHON
#app.route("/delayRequest", methods=['POST', 'GET'])
def delay():
time.sleep(10)
return;
However, opposed to calling the function, it running, then having a delay of 10 seconds before being called again, the webpage just peppers me with "called" alerts, meaning liveCommentaryCall is just getting called instantly on loop somewhere?
I can't see anywhere in code which should be causing this, which makes me think theres some underlying principle I'm overlooking.
Question
Is the error in the fact that I cant use a python script like this, or am I just not coding this idea correctly?
Instead of implementing liveCommentaryCall recursively, you can use the setInterval function in the script:
<script>
setInterval("liveCommentaryCall()",1000); //call every second
function liveCommentaryCall(){
.
. // bunch of code to update the page
.
$.ajax({
url: "/delayRequest",
type: "POST",
data: JSON.stringify(""),
success: function(response) {
alert("RESPONSE RECIEVED");
},
error: function(delayError) {
alert("Something's gone wrong!");
}
});
}
</script>
I've searched SO, and every question seems to be asking how to wait for an AJAX call to complete. I am asking how not to wait for an AJAX call to complete.
I have an e-commerce site that does some heavy image manipulation via PHP. The manipulation is triggered via AJAX calls.
I am trying to speed up the user experience, so I have modified the code to first have PHP render a thumbnail (the operation completes quickly), then trigger a second AJAX call that tells PHP to render the full image (which can take a few minutes).
The "Add To Cart" operation is also an AJAX call. The problem is that the "Add to Cart" call is unable to complete until the previous AJAX call is completed.
Sequence:
AJAX call A requests thumbnail be generated.
The success callback for call A:
a. Displays / enables the "Add to Cart button"
b. Triggers AJAX call B, for the full image to be generated.
Clicking "Add to Cart" triggers AJAX call C, which does not complete until call B completes.
Relevant javascript:
/** Call A - make call for thumbnail generation **/
$.ajax({
url: 'index.php?route=decorable/image/thumbnail',
type: 'post',
data: image_data,
dataType: 'json',
success: function(json) {
if (json['success']) {
$('#button-cart').show();
/** Call B - make call for *full* layout generation **/
$.ajax({
url: 'index.php?route=decorable/image',
type: 'post',
data: image_data,
dataType: 'json'
});
});
/** Call C - this AJAX call starts, but does not complete, until call B completes **/
$('#button-cart').click(function() {
$.ajax({
url: 'index.php?route=checkout/cart/add',
type: 'post',
data: cart_data,
dataType: 'json',
success: function(json) {
if (json['success']) {
$('.success').fadeIn('slow');
}
}
});
});
Am I misunderstanding, or should call C be able to complete even if call B is not complete?
If you believe that the PHP is holding up the experience, then is there a good way for to me to trigger PHP to begin executing, but still send the response back for the thumbnail AJAX call?
In my experience this was caused by PHP sessions been used, when you're sure in the code (all ajax requests) that you will not have to modify sessions then you should call:
session_write_close()
This will then allow other requests to be made simultaneously.
Further reading: http://www.php.net/manual/en/function.session-write-close.php
Most browsers support at max two async request at time. You can do nothing.
Be aware, that only applying session_write_close() [answer of Jono20201] may not resolve the problem, if You have enabled output buffering (default in PHP 7+). You have to set output_buffering = Off in php.ini, otherwise session won't be closed immediately.
I'm building a web app to help with a restaurant, and my client was very clear on that he wanted the app to be asynchronous.
During localhost development I used setInterval to update the page periodicaly using variations of this code for each button:
$('#showWaitlist').click(function(){
showWaitlist();
stopUpdate(interval);
interval = setInterval(function() { showWaitlist();}, intervalTime);
});
function stopUpdate(){
clearInterval(interval);
}
So that every time I click a button it stops the past interval and starts it's own.
It worked fine, however, when I moved the app to the server the intevals would sometimes overlap each other, specially when the server was on heavier-than-avarage load or when I used a phone to access the site.
If setInterval and stopUpdate are js shouldn't they work on clientside and be practically instant? What could cause this "jumping" between intervals?
This is a link to the website: http://www.emc2.mx/Pruebas/unicenta/PostodoroApp/
Please note that the problem not always happens, but you can probably replicate it if you opne it on your phone.
I'll add showWaitlist here, but I doubt there's something wrong with it.
function showWaitlist(){
$.ajax({
type:'GET',
url: 'waitlist.php',
dataType: 'html',
success: function(result){
$('#result_table').html(result);
} // End of success function of ajax form
}); // End of ajax call
}
You will need to clear the interval in
the success of the ajax call on your code by adding the following line
clearInterval(interval); // stop the timer once the time finishes.
after the following line
$('#result_table').html(result);
You need to have access of the interval variable in the success method callback
i have a java code that processes a csv file 1 line at a time. I want to update the user with the record being currently processed like (1 of 1000 completed, 3 of 1000 completed and so on). This is a piece of code i have written so far. The first call is the PROCESS FILE and second call with a repetition of 3 seconds is the GET CURRENT RECORD.
$.ajax({
type : "POST",
url : "/service_member_import.jsp",
aysnc: false,
data: {
"action":"processrecords",
"ms": new Date().getTime()
},
dataType : 'html',
success : function(data) {
console.log("file processed");
},
error: function(){
alert("Error retrieving data");
}
});
setInterval(update, 3000);
update();
function update() {
$.ajax({
type : "POST",
url : "service_member_import.jsp",
data: {
"action":"getStatus",
"ms": new Date().getTime()
},
dataType : 'html',
success : function(data) {
console.log("current data\t");
console.log(data);
},
error: function(){
alert("Error retrieving data");
}
});
}
The current behavior is that it processes all the records (ie 1st ajax call) and then gives me the current record processed (ie 2nd ajax call). ie both ajax calls are not taking place parallel.
Please suggest me if you think there are better ways to achieve this. Or if we can make these ajax calls parallel.
It looks like your webserver is blocking the second request until the first one is finished...
You need a non-blocking or threaded server for this to work.
What platform are you using?(Ruby/Rails, Node/Sails, PHP/Cake, Python/Django etc.)
I finally figured out that the two ajax calls were being made parralely. It was just that the number of records were too less hence the first ajax call finished almost immediately and gave a feeling that the second ajax call was only made at the end.
As soon as i increased the records to 30,000. I could see that second ajax call did interrupt in between the first ajax call.
Thank you for the help :)
I have a python script that's doing around 8 or 9 specific steps. These steps are being logged in a file. For web GUI to display status change, or error messages, I am using the script belowjquery PeriodicalUpdater plugin.
I need the program to run simultaneously so that as the value in the file changes,it gets polled and displayed.
Please find my jquery code below.
Note the url "/primary_call/" takes around 2 and half minutes to execute. Problem is async :false is not working. The browser waits for 2.5 minutes, and then gets into the next level.
I tried in Firefox and Chrome and it gives the same result.
When I call the URL of another browser tab, it works perfectly, but I am unable to run both script components simultaneously, when I try calling from the same page.
What should I do so that the browser initiates "/primary_call/", which runs a Python script in the background, at the same time moving ahead to the portion called PeriodicUpdate.
$(document).ready(function()
$.ajax({
type: 'GET', // Or any other HTTP Verb (Method)
url: '/primary_call/',
async: false,
success: function(r){
return false;
},
error: function(e){
}
});
$.PeriodicalUpdater({
url : '/static/12.txt',
method: 'post',
maxTimeout: 6000,
},
function(data){
var myHtml = data + ' <br />';
$('#results').append(myHtml);
});
})
Setting async:false means you are making the process synchronous, so the browser will hang on it until it is finished -- it can't move on to your other method. Removing that option will make the call asynchronous (which it is by default, as it should be) at which point the browser will initialize each ajax call in a separate thread.
In short, remove async:false.