I want to know that suppose you did an ajax request to a page that runs PHP code. The page outputs some data (using flush() method or otherwise) but because of a 30second timeout or some other error, the php request ends.
Now when the request ends, I want to find out about it on client side and restart the request.
i.e suppose I have something like this
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==3 && xmlhttp.status==200){
document.getElementById("A").innerHTML=xmlhttp.responseText;
}
else if(xmlhttp.readyState==4 && xmlhttp.status==200){
document.getElementById("A").innerHTML=xmlhttp.responseText;
//plus some additional code to end the process
}
else if(xmlhttp.status== SOMETHING /*WHAT DO I ADD HERE TO KNOW THAT THE SERVER HAS TIMED OUT OR SOMETHING SO I CAN RESTART THE XMLHTTP CYCLE */){
//code to resend xmlhttp request.
}
}
One strategy I used was to set a timer in JS, and then clear it if the call was successful.
var myTimer = setTimeout(stuffToDoOnFailure, 6000); // 6 secs
ajaxCall(function callBack() {
clearTimeout(myTimer);
});
EDIT:
Of course, if the ajax call succeeds after 6 secs, you might end up with both stuffToDoOnFailure and callBack being executed, so you want to handle that case somehow. That depends on your app, though.
Related
function loadxmldoc()
{
var xmlhttp;
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
else
{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","ajax_info.php?fname=sakthi&lname=karthiga",false);
xmlhttp.send();
}
ajax_info.php
<?php
echo( "hello"."<br>".$_GET["fname"].$_GET["lname"]);
?>
in this code i change the ajax status as FALSE but stil working same as TRUE
can u tell whats the difference b/w TRUE and false? if i change false what will going on serverside
I suppose that you are talking about the third parameter of the open function. It indicates whether the request should be asynchronous or not. In both cases the exactly same request will be sent to the server. The difference will be on the client. If you use asynchronous (which is the recommended for AJAX) the client browser will not freeze during the execution of the request and the send method will return immediately. Once the execution on the server finishes, the callback you subscribed to will be invoked.
If you set the parameter to false the send method will block and freeze the client browser during the entire execution of the request to the server. This completely defeats the whole purpose of AJAX but it is used by some people that want to use the results of the request outside of the success callback. Do not do the same mistake.
I would very strongly recommend you to always use asynchronous AJAX requests (true) and not blocking calls.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best way to manage long-running php script?
I have to built a big email list.Everything works perfectly,but when i submit the form page is loading untill every email is send.So i want this email sending script run in background.and notice the user that script is runnign in background.
I cant use Ajax.
i want something like.. proc_open,exec,shell_exec..
You can have cron job which would run php script which will get queue from db and send email
On main script you just need to add emails to queue
I would use ajax only if you need progress bar. With ajax solution you would need to keep window open until it's ended.
You could build an AJAX call that calls the php script. This way, your site will still be operational while the request is fulfilled. And when it's finished, your AJAX will return and you can show a messagebox to the user.
For more information, check at least this and if you understand what AJAX is and what it does, use it with this
Ajax request would be the best choice for this. You can send a request using javascript and even report progress to user (which might require some additional work)
If you find ajax too difficult - run script in an iframe. This is not the most elegant, but the most simple method.
Submit the form with AJAX and update the progress in a Div
For example - write to some place "A"(db or file) current state of your script runtime: "complete"/"incomplete". After start script in background send to your user waiting page which using AJAX handling changes at "A".
This Ajax script will execute a PHP file on the background. It could also send the response to a HTML element if you want.
<script type="text/javascript" language="javascript">
function execute(filename,var1,var2,var3)
{
var xmlhttp;
if(window.XMLHttpRequest)
{
//Code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else if(window.ActiveXObject)
{
//Code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else
{
alert("Your browser does not support AJAX!");
}
var url = filename+"?";
var params = "var1="+var1+"&var2="+var2+"&var3="+var3;
xmlhttp.open("POST", url, true);
xmlhttp.onreadystatechange=function()
{
if(xmlhttp.readyState==4)
{
//Below line will fill a DIV with ID 'response'
//with the reply from the server. You can use this to troubleshoot
//document.getElementById('response').innerHTML=xmlhttp.responseText;
xmlhttp.close;
}
}
//Send the proper header information along with the request
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.setRequestHeader("Content-length", params.length);
xmlhttp.setRequestHeader("Connection", "close");
xmlhttp.send(params);
}
</script>
You can try to run the script through an ajax function as well if you don't want to set cron script.
PHP has an function that can keep an process running even if the user that requested the page leaves the page : ignore_user_abort if you check the comments there you can see this example :
<?php
ignore_user_abort(1); // run script in background
set_time_limit(0); // run script forever
$interval=60*15; // do every 15 minutes...
do{
// add the script that has to be ran every 15 minutes here
// ...
sleep($interval); // wait 15 minutes
}while(true);
?>
It IS an pure php cron job BUT, the risk with this script is that it continues indefinitely or atleast untill you reset/kill php.
Setting the set_time_limit(0); to set_time_limit(86400); would kill the script after an day.
This should point you in the right direction/.
IMPORTANT
After the problem by the OP, it is advisable to only run this script if you have SSH access to the server so you can KILL/RESTART php apache in case the server keeps hanging.
Also do not run the script on a LIVE server.
I have a worker thread that sends out a request to the server for data using an XMLHttpRequest. That request points to a php file that basically checks the current integrity of the information that the client has and if the client needs the new information then it is sent. Otherwise the server checks information until the client needs a response. After the server responds the whole process is repeated.
The problem arises when the browser realizes the script isn't responding and gives the user the option to stop the script. As you can see, this isn't the intended result. So what's the best way to continue using the comet-like structure without confusing the browser?
EDIT: I realized why the script is hanging, I repeated the whole worker thread instead of repeating the somewhere deeper inside the thread. So I guess my question now where to start the process again, after it finishes.
<?php
//Client sends their current id
if(isset($_GET['id']))
$id = $_GET["id"];
//if id doesnt match servers id send them a new one
//other wise do not respond
$server_id = file_get_contents("ids.txt");
while($server_id == $id){
$server_id = file_get_contents("ids.txt");
sleep(1);
}
echo $server_id;
?>
Javascript:
self.addEventListener('message', function(e) {
var data = e.data;
switch (data.cmd) {
case 'start':
getInfo(data.id);
self.postMessage('ID :: ' + response);
break;
default:
self.postMessage('Unknown command');
};
}, false);
var response = null;
var request = new XMLHttpRequest();
function getInfo(inputID){
var url = "serverResponse.php?id=" + inputID;
request.open("GET", url, false);
request.onreadystatechange = updateState;
request.send(null);
}
function updateState(){
if(request.readyState == 4){
if(request.status == 200){
response = request.responseText;//getInfo(data.id);
}
}
}
html:
<html>
<script type="text/javascript">
function sayHI() {
var id = "666";
worker.postMessage({'cmd': 'start', 'id' : id});
}
var worker = new Worker('AjaxWorker.js');
worker.addEventListener('message', function(e){
document.getElementById('result').textContent = e.data;
//Some data has been received so go ahead and make another call to the server
//This is where the script hangs because the worker waits for a response
sayHI();
}, false);
</script>
<body>
<button type="button" name="submit" id="submit" onclick="sayHI()">Submit</button> </br></br>
<output id="result" name="result">Result</output>
</body>
</html>
Your line:
request.open("GET", url, false);
has the async argument of open() set to false, meaning that the JavaScript execution flow completely stops on that Ajax call until it completes. Your webpage is completely frozen until that synchronous call resolves, and since you're using long polling, that won't happen for a very long time. Thus, your browser's interpreter sends you a warning that script execution is taking a suspiciously long time. (This warning is completely legitimate, too -- you can't do anything at all on your page until the synchronous call resolves.)
You need to use request.open("GET", url, true);. Just move anything that needs to happen after the Ajax call and place it inside the onreadystatechange callback. When the server finally responds, the updateState function will fire. Anything that should happen in response to a "comet push" (i.e. the resolution of a long-poll query by a response from the server) needs to go in that callback.
Asynchronous Ajax will allow the script execution to continue and won't cause your JS interpreter to hang. Instead of waiting for the long-polling query to resolve, the script flow will move right past it, and at some later time the onreadystatechange callbacks will be called with new information from the server.
EDIT:
The JavaScript interpreter only has one thread. If that thread is utilized nonstop for a long period of time, the browser will suspect something has gone wrong and issue a warning. Your synchronous Ajax call grabs the single JS thread and doesn't let go until the server finally replies. As I said earlier, during that long time, nothing else can happen on the page. The interpreter is stuck on that call.
With synchronous Ajax, your flow looks like this:
send synchronous request
wait
and wait
and wait
(meanwhile, nothing else can get done)
and wait...
....
finally a response comes!
use the response to update the page
Consider this superior asynchronous Ajax alternative:
send ansyc request
[the interpreter sleeps and the browser is happy]
a response comes!
the request's readystatechange event fires now
the onreadystatechange handler uses the response to update the page
In the second example, the interpreter gets to take a break instead of waiting for the Ajax request to resolve. Your onreadystatechange handler function is fired whenever the Ajax call comes back from the server. If your call is synchronous, the interpreter does nothing until the call resolves. If your call is asynchronous, the interpreter is free to do anything it likes -- including rest and not cause a browser warning -- until the call resolves and it executes your onreadystatechange handler.
You don't say what technique you are using to implement reverse AJAX (HTTP polling? HTTP streaming? WebSockets? Something else?) If you're using polling, the server is supposed to respond promptly, even if it's "nothing new here".
If you're holding a connection open, this can cause a problem; HTTP limits a browser to two simultaneous connections to a server. In that case, the browser and any other scripts only have one connection to work with; this can cause the browser to think things are blocked. A standard approach to this is to create a separate host name for comet interactions.
If you use a WebWorker, the browser won't complain about it being blocked. (However, the issue of connection count could still cause problems.)
I was studying about AJAX and it was about form validation where as soon as the person fills in the username for signing up, it is checked using AJAX while he still can enter all the other fields. so i issued a request and on readystatechange i called a callback function. now i have studied PHP before this, but i never came across returning information from the server. I mean to say that what all goes in my PHP script, and how does i make sure that the request issued is responded as desired. i dont want the exact code, if just bits of it,or the algorithm can be improved,
For example, i know i passed the username along with the url to the php script, and then i checked if it matched any of the existing usernames in my database(MYSQL and queries) , and normally i would just print the form again if there's a match, else i will exit();
but what do i do when i want to respond back to the object request?
It's really quite easy when you get the hang of it. It's even easier if you use jQuery's AJAX, http://api.jquery.com/jQuery.ajax/ - though don't bloat your site with this unless you intend on using loads of javascript (and use google's cdn for it)
In javascript, you make an XHR request either GET or POST to your PHP script. Usually you'll need to create a separate file for the view to any AJAX requests, because AJAX requests shouldn't bring the webpage's template back as well (i.e. if you wanted to return '1', it should only return '1', not <html><body>1</body></html>. ... etc.
Example:
blah.com/index.php needs some AJAX requests.
blah.com has javascript that creates the ajax request by sending a datastring/url (e.g. ajax.php?act=verify_email&email=a#c
blah.com/ajax.php would then have some PHP code that could switch($_GET['act'] or $_POST['act']) with a 'case' statement of 'verify_email'. That code would run some regex or something, and return 1 or 0 to say 1(valid), 0 (invalid). The 'onreadystatechange' holds the status of the request, so I think its usually a function i.e.:
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
You access the returned '0' or '1' through the xmlhttp.responseText, where xmlhttp is var xmlhttp =new XMLHttpRequest();
Then you just run the request
xmlhttp.open("GET","ajax.php?act=verify_email&email="+document.getElementById('email').value,true);
xmlhttp.send();
Update: In your case with the form, onblur (when they move out of focus of an element), you could run the AJAX request sending the value of the input, and then in the ajax.php script as a GET or POST request, you could run your validation query to check if the user exists already, or if the username isn't valid or whatever. Once the request has completed, it will return the results in the responseText value. Use firebug's console to check the result of an AJAX request if you can, its very useful.
This might not be what you mean but can't you:
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
// do something with "xmlhttp.responseText"
var x = xmlhttp.responseText
}
And in the php just:
echo $x;
That works fine for transmitting strings and other info...
as a fix to a previous problem of mine, i have thought to run a cURL script using JavaScript to prevent my site waiting for a response of each one.
at the moment I have this script given by a friend and i have noticed something.
Link to JS file
My question is if I were to remove the following lines, would it mean that the page would not wait for a response?
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
setTimeout("location.reload(true)",1500);
}
}
Thanks.
If you remove the lines, it will not go anywhere.
If you want to speed it up, get rid of the setTimeout line, that is not nessecary.
If you were to remove the if statement, and just do the window.locaiton line, it will fire before the request is made since that onreadystatechange fires to tell you when the request is opened, started, transferring, and done.
Ajax 101 Article