How can I use the $.ajax() function to display output in real time. Right now I am using it in this context:
$.ajax({
type: 'get',
url: 'process.php',
data: 'foo=boo',
success: function(output) {
$('div#results').html(output);
}
});
The above displays the output recived from the PHP script only AFTER the script has fully executed. So if in the php script you had the following:
echo 'Hello for the first time';
// some code
echo 'Hello again';
// some code
echo 'Are you still here?';
The output would be all those echos all at one. Instead, is there any way I can update the output received from the PHP script one after another as the requests are being fulfilled by PHP in real time?
I know how to update things in real time when working entirely in the realm of JavaScript, for example: checking if the input being typed is at least 10 characters long using the keyup() event as a trigger to check after every entered key and displaying a message to enter something more which disappears as soon as the 10th character is typed.
But how to do something like this when the output is coming from a PHP file? is it even possible?
Reason why I need to do this is because I would like to have a status screen that shows how much progress has been made and what part of a task the script is currently handling, like how desktop apps have.
It is not possible. You should split this task in to parts - one is long running task that updates it's status in database, and other task that just fetches status from database and displays progress to users.
Umm, nope. Thats not possible. The best you can do is, Try breaking down your php file and calling multiple ajax requests for each of those files.
Related
I have php script which can take quite a lot of time (up to 3-5 minutes), so I would like to notify user how is it going.
I read this question and decided to use session for keeping information about work progress.
So, I have the following instructions in php:
public function longScript()
{
$generatingProgressSession = new Zend_Session_Namespace('generating_progress');
$generatingProgressSession->unsetAll();
....
$generatingProgressSession->total = $productsNumber;
...
$processedProducts = 0;
foreach($models as $model){
//Do some processing
$processedProducts++;
$generatingProgressSession->processed = $processedProducts;
}
}
And I have simple script for taking data from session (number of total and processed items) which return them in json format.
So, here is js code for calling long script:
$.ajax({
url: 'pathToLongScript',
data: {fileId: fileId, format: 'json'},
dataType: 'json',
success: function(data){
if(data.success){
if(typeof successCallback == "function")
successCallback(data);
}
}
});
//Start checking progress functionality
var checkingGenerationProgress = setInterval(function(){
$.ajax({
url: 'pathToCheckingStatusFunction',
data: {format: 'json'},
success: function(data){
console.log("Processed "+data.processed+" items of "+data.total);
if(data.processed == data.total){
clearInterval(checkingGenerationProgress);
}
}
});
}, 10000)
So, long scripted is called via ajax. Then after 10 seconds checking script is called one time, after 20 second - second time etc.
The problem is that none of requests to checking script is completed until main long script is complete. So, what does it mean? That long script consumes too many resources and server can not process any other request? Or I have some wrong ajax parameters?
See image:
-----------UPD
Here is a php function for checking status:
public function checkGenerationProgressAction()
{
$generatingProgressSession = new Zend_Session_Namespace('generating_progress');
$this->view->total = $generatingProgressSession->total;
$this->view->processed = $generatingProgressSession->processed;
}
I'm using ZF1 ActionContext helper here, so result of this function is json object {'total':'somevalue','processed':'another value'}
I'd
exec ('nohup php ...');
the file and send it to background. You can set points the long running script is inserting a single value in DB to show it's progress. Now you can go and check every ten or whatever seconds if a new value has been added and inform the user. Even might be possible to inform the user when he is on another page within your project, depending on your environment.
Yes, it's possible that the long scripts hogs the entire server and any other requests made in that time are waiting to get their turn. Also i would recommend you to not run the check script every 10 seconds no matter if the previous check has finished or not but instead let the check script trigger itself after it has been completed.
Taking for example your image with the requests pending, instead of having 3 checking request running at the same time you can chain them so that at any one time only one checking request is run.
You can do this by replacing your setInterval() function with a setTimeout() function and re-initialize the setTimeout() after the AJAX check request is completed
Most likely, the following calls are not completing due to session locking. When one thread has a session file open, no other PHP threads can open that same file, as it is read/write locked until the previous thread lets go of it.
Either that, or your Server OR Browser is limiting concurrent requests, and therefore waiting for this one to complete.
My solution would be to either fork or break the long-running script off somehow. Perhaps a call to exec to another script with the requisite parameters, or any way you think would work. Break the long-running script into a separate thread and return from the current one, notifying the user that the execution has begun.
The second part would be to log the progress of the script somewhere. A database, Memcache, or a file would work. Simply set a value in a pre-determined location that the follow-up calls can check on.
Not that "pre-determined" should not be the same for everyone. It should be a location that only the user's session and the worker know.
Can you paste the PHP of "pathToCheckingStatusFunction" here?
Also, I notice that the "pathToCheckingStatusFunction" ajax function doesn't have a dataType: "json". This could be causing a problem. Are you using the $_POST['format'] anywhere?
I also recommend chaining the checks into after the first check has completed. If you need help with that, I can post a solution.
Edit, add possible solution:
I'm not sure that using Zend_namespace is the right approach. I would recommend using session_start() and session_name(). Call the variables out of $_SESSION.
Example File 1:
session_name('test');
session_start();
$_SESSION['percent'] = 0;
...stuff...
$_SESSION['percent'] = 90;
Example File 2(get percent):
session_name('test');
session_start();
echo $_SESSION['percent'];
I'm learning and experimenting with jquery/ajax as I develop a website. I have a page that updates a database. I would like a 'sequence' of responses to display on the screen when the user submits their data (I've seen this done on many other sites).
For instance... user submits form and the page displays:
Received Input
Checking Database - recond number xy
Updating Database
Retrieving Information
etc etc
This is just an example but you get the idea.
I have an ajax call that is initiated on 'click' of the submit button (getFormData just serialises all the form data for me and works fine):
var toSend = getFormData($upgrade_db_form);
var formMessageBox = $("#displayResults");
$.ajax({
url: ajaxurl,
data: {
action: "database_action",
formData : toSend
},
type: 'POST',
dataType: 'TEXT',
beforeSend: function() {
//$form.fadeOut('slow');
formMessageBox.html("starting it up");
},
success: function (data) {
formMessageBox.empty();
formMessageBox.html(data);
error: function (xhr) {
// formMessageBox.html("Oops error!");
}
});
I have a function which gets called by ajax:
function upgrade_database_function() {
echo "testing ";
for($i = 0; $i < 99; $i++) {
echo "percent complete ".$i."%";
}
echo "done ";
die(); // this is required to return a proper result
}
I'm using Wordpress and all the ajax side of things works fine, it passes the form data correctly etc, it's just that I get one long output as though it's cache'ing all the echo's up instead of outputting them in sequence.
I've gone through the jquery ajax documentation and couldn't find how to make it behave the way I want it to. I can live with it the way it is but I think it would look a lot better if I could get it working the way I would like.
Can this be done this way or do I need lots of sequential ajax calls to make it work?
I don't know PHP, but i'm guessing that the echo is just writing to the response buffer... so when all the echos are done the whole response will be returned and you would get the effect that you are seeing... You would need to go with a polling system or something along those lines to get the latest status' from the server and display them I would think... Maybe there is some system in PHP that allows this, but as I said, I don't know PHP.
An Example of Long Polling can be found in this article.
http://www.abrandao.com/2013/05/11/php-http-long-poll-server-push/
WARNING: You may have to do some manual managing of locking of the session in PHP so that your long running call doesn't lock your polling ajax calls: See here:
http://konrness.com/php5/how-to-prevent-blocking-php-requests/
Note that you would likely be wanting to:
create one ajax call that starts the execution of some coded that will take a while... you could put messages that have been generated into a session variable for example in a list of some sort. You would need to lock/unlock the session as mentioned to prevent suspension of AJAX polling calls.
you would create a polling method like in the article that might check the session every 500ms or something to see whether there are any more messages, lock the session, remove those messages and return those messages to the client side and display them.
WARNING: Again, I'm not a PHP person, I may have done this once in my life in PHP (can't remember exactly) but I may be wrong and this may not work, from what I've seen though it looks like it is achievable. Hope this gets you on your way!
I need to process a very long running process in PHP (grepping big text files and returning matching lines). When we run an average query from the command line, the process may take 10-15m.
I wanted to implement in PHP/jQuery, whereby I started the query, then showed incremental results as they came back.
I implemented something close, where I had one ajax call doing the search (worked fine), and had a periodic timer function running calling a second method in the class to get the results. However, I realized that the 2nd call would really create a new class instance, so the $this->current was different between the main query and the period update timer.
Here's the javascript I was trying (I was kicking it off when clicking a form button):
<script>
function update_status(data) {
alert(data);
jQuery.each(data, function(key, val) {
if ( key == "progress" )
$("#progressbar").progressbar({ value: val });
});
}
function progress_setup() {
setInterval(function() {
jQuery.ajax({
type:'POST',
dataType:'json',
complete:function(XMLHttpRequest, textStatus){
update_status(textStatus)
},
url:'<?php echo url_for("#grep_status"); ?>'
})},
2000);
}
function grep(elements) {
jQuery.ajax({
type:'POST',
dataType:'html',
data:jQuery(elements).serialize(),
success:function(data, textStatus){jQuery('#results').html(data);},
beforeSend:function(XMLHttpRequest){progress_setup()},
url:'/grep'});
}
</script>
But, this doesn't appear to be the right track. The core issue seems to be:
Long running task in PHP
How do you get the status of that task back to a progress bar, and an incremental results dialog?
TIA
Mike
You have to share the state of your operation either using a database or a file. Then in your /grep operation you periodically write the state in the database or the file (updating the state).
Then you need another script (like /grep_state) which reads the state and returns it to the client.
What you can't do is share the state using a PHP-object instance since this it's scope is limited to a single request. You have to persist the state.
The other Problem might be that your long running task is terminated because of a request timeout either by the webserver or the browser. I would either run the script in CLI-mode (detached from the webserver/request) or write a simple job-scheduler which runs as a daemon.
The daemon gets the parameters from a socket (or any other means of communicating with other processes) and starts the php-CLI with your worker-script. The state is also shared using files or a database.
Seems like the easiest thing to do is to split the task up in php and send some sort of flag back to your client side app to tell it when it's finished.
Maybe:
Get the size of the file.
Begin the query, return the first result with a character number.
Update progress bar.
Start next query beginning at last character number, return second result with character number.
Update progress bar.
Continue until reached end of file.
Although that wouldn't give you a perfect progress update, it would indicate how far you've searched into the file.
I think the key is to set up your server with parameters that allow you to limit/filter your query results.
You can try flushing your output early--this varies according to your server settings, however. For example:
// Script starts, does first block of program
echo "1";
flush();
// Second block starts and finishes
echo "2";
flush();
// Etc...
After each block completes, flush a response.
the reponseText should be like this on PHP
echo "<script>alert('test')</script>";
But nothing happen. How do I return Javascript code?
An ajax call is up to the caller to decide what to do with it (depending upon what type of data is returned). In this case, if your caller isn't prepared to execute this, then nothing will happen with it. Depending upon what the real code wants to do here, there are a number of different possibilities for handling the returned result from the ajax call.It could be formatted as JSONP so it calls a function in your main page code to process the returned data. You could return full JS (without the tags) and do an eval() on it after the host page (generally not considered a wise idea due to some security risks) or it could be just added to the current page and let the browser just parse whatever you put in there.Usually, an Ajax call returns pure data and your host page code processes that data and holds the code for deciding what to do with it. This is the safest mechanism because there's no way for anything that hijaacked a connection to inject code into your page (all it can do is change the data).
You've returned it as text. Now all you need to do is insert that text onto the page somehow:
document.body.innerHTML += response;
There's a lot going on, and a lot of assumptions made, but that's the simplest way to do it.
(Well, that's not entirely true. The easiest way to do it would be to just return the JavaScript, and then eval it.)
here's a simple example. But don't include the <script> tags for this tough
$.ajax({
type: "GET",
dataType: "text",
url: "jsLoader.php",
success: function(data){
eval(data);
}
});
Can any one please explain this:
var js_var = 'hello';
$.ajax({
type: "POST",
url: "some.php",
data: "js_var="+js_var,
success: function(msg){
alert( "Data Saved: " + msg );
}
});
I need to know what is returned by the PHP file in this case... The PHP file can be assumed to return whether jsvar exists in the db or not...
The PHP file will return whatever the result of processing the data params (js_var=hello) is. The output will be received by the client as a string (msg).
Your output from PHP script either with echo/print or even HTML is returned in the msg argument of success callback function.
For example, if you do this from PHP script:
echo 'hello world';
The msg will be equal to hello world
Assuming that this is in reference to PHP Javascript variable help then some.php can do whatever you need to do. The actual some.php was just a place holder for whatever script you needed run was named.
Instead of the output of that PHP file being sent and rendered in browser, it is sent and put into the msg variable. What you send back could be a block of HTML to be shoved into a div for rendering, a simple OK, or a JSON object, or XML. As you are writing the code on both ends of the communication, you can do whatever you want.
For example, if you were creating a user creation form, you could have a script, that after the user name box loses focus, goes and makes an AJAX call, then returns either OK or an error message, then you could display that next to the user name box.
EDIT:
As other people have mentioned, it would be best going through a few tutorials about jQuery and AJAX in general. A quick google turns up a few decent ones:
http://docs.jquery.com/Tutorials:Getting_Started_with_jQuery
http://www.ibm.com/developerworks/library/x-ajaxjquery.html
http://www.ibm.com/developerworks/opensource/library/os-php-jquery-ajax/index.html
I've found that the IBM developerworks articles to be rather clear and concise time and again.
use firefox , firbug or ie fiddle to the see the output.
Firebug is really nice , there is a panel called net , open that and you can see the result from php.