When I'm taking my query using Ajax on jQuery, o try use the method of long pull but my server is shutdown or dont response, my website becomes too slow like in stanby, or freezed what can i do?
MY PHP;
session_start();
$chat=new chat;
$class=new tools;
$idenvia=isset($_GET['idenvia'])? $_GET['idenvia']: '';
$idreceptor=isset($_GET['idreceptor'])? $_GET['idreceptor']: '';
$cantidad= isset($_GET['cantidad'])? $_GET['cantidad']: '';
$control=$_GET['control'];
//$ultima_modif=isset($_SESSION['fecha'])?$_SESSION['fecha']:0;
if($control==1){
echo json_encode($chat->leer_chat($idreceptor,$idenvia,$control,$cantidad,NULL));
}
if($control==2){
$dir='log/log_'.$_SESSION['id'].'.txt';
$ultima_modif=filemtime($dir);
$modifica_actual=isset($_GET['tiempo'])? $_GET['tiempo']: 0;//0
set_time_limit(0);
while($ultima_modif<=$modifica_actual){
clearstatcache();
$ultima_modif=filemtime($dir);
sleep(1);
//echo '{"0":{"activo":2}}';
//flush();
}
$res=$chat->leer_chat($_SESSION['id'],NULL,$control,$ultima_modif);
echo json_encode($res);
//unlink($dir);
flush();
}
This is my JQUERY code, here i take th response of my php with AJAX
function leer_chat_interval(){
$.ajax({
url:enlace,
type:'GET',
async:true,
data:{'control': 2,'tiempo':tiempo},
success:function(dato){
eval('var json='+dato);
if(json[0].activo==1){
//if(json.length!=0){
leer_chat(json[0].idenvia,json[0].idrecibe,1,json[0].nombre,json[0].mifoto,1,1);
$('#msg_chat'+json[0].idrecibe).attr('name',"{'recibe':'"+json[0].idenvia+"','envia':'"+json[0].idrecibe+"','foto':'"+json[0].mifoto+"'}");
setTimeout(function(){
$('#header_chat'+json[0].idenvia).css('background-color','#09C')
setTimeout(function(){
$('#header_chat'+json[0].idenvia).css('background-color','#F90')
},1000)
},1000);
tiempo=json[0].tiempo;
noerror=true;
}else{noerror=false;}
},
datatype:"json",
complete:function(dato){
if(!noerror){
setTimeout(function(){
leer_chat_interval()
},5000)
}else{
leer_chat_interval();
noerror=false;
}
},
timeout:30000
});
}
Your problem is this:
while(1)
You are not supposed to have a script looping infinitely to handle your ajax "long polling"; instead each ajax call runs through a finite request, collects the result, and repeat. What is happening in your example is that everytime your ajax request fires, a new infinitely running script is started; naturally the server collapses after a accumulating several of these.
Related
For the backend of my site, visible only to a few people, I have a system whereby I communicate with a php via ajax like so:
function ajax(url, opts) {
var progress = false, all_responses = [], previousResponseLength = "";
var ajaxOptions = {
dataType: "json",
type: "POST",
url: url,
xhrFields: {
onprogress: function(e) {
if (!e.target.responseText.endsWith("\n")) return;
var response = e.target.responseText.substring(previousResponseLength).trim();
previousResponseLength = e.target.responseText.length;
var responses = response.split(/[\r\n]+/g);
var last_response;
for (var k in responses) {
if (responses[k] === "---START PROGRESS---") {
progress = true;
if (opts.onProgressInit) opts.onProgressInit();
} else if (responses[k] === "---END PROGRESS---") progress = false;
else all_responses.push(last_response = responses[k]);
}
if (progress && last_response !== undefined) opts.onProgress(JSON.parse(all_responses[all_responses.length-1]));
}
},
dataFilter: function(data){
return all_responses[all_responses.length-1];
}
}
$.extend(ajaxOptions, {
onProgress: function(data){
console.log(data);
}
});
return $.ajax(ajaxOptions);
}
And an example of a never-ending php script (until the user closes the connection):
const AJAX_START_PROGRESS = "---START PROGRESS---";
const AJAX_END_PROGRESS = "---END PROGRESS---";
session_write_close(); //fixes problem of stalling entire php environment while script runs
set_time_limit(0); //allows to the script to run indefinitely
output(AJAX_START_PROGRESS);
while(true) {
output(json_encode(["asdasd" => "asasdas"]));
sleep(1);
}
function output($msg) {
echo preg_replace("`[\r\n]+`", "", $msg).PHP_EOL;
ob_flush(); flush();
}
This allows me through 1 ajax request to 'poll' (am I using that term correctly?)
So if I want to execute a very long php script I can now check its progress, and the last response is delivered via jqhxr.done(callback).
Or, as in the example php script, I can open a connection and leave it open. Using sleep(1); It issues an update to the $.ajax object every 1 second.
Every response has to be json encoded, and if the response is 1 very long json that comes over multiple 'onprogress' calls, it waits until the end of the message (if responseText.endsWith("\n")) we're ready!)
My remote shared server didn't allow websockets so I made this. If the user closes the connection, so does the php script.
It's only got to work for a few admins with special privileges, and I don't need to worry about old browsers.
Can anyone see anything wrong with this script? Through googling I haven't found anybody else with this kind of method, so I expect something is wrong with it.
Extensive testing tells me it works just fine.
You invented long polling request, actually it's wide used as fallback to websockets, so nothing wrong with it.
About your code it's hard to say without testing, but when using such methods as long-polling, you need to double check memory leaks on browser side and on server side.
I'm currently trying to get a PHP loop status and update a HTML5 progress bar.
The loop is triggered by a button click and set to 5000 with 1sec sleep() after every execution. I of course also made an Ajax request to which reuqests the current loop number every second and update the progress bar. However the request always waits until the loop is completed and shows me a number like "1234567891011..."
This is my JQuery code which is very simple because it's only for testing and learning purpose
function getStatus() {
$.ajax({
url : 'ajax.php',
dataType: "html",
type: "POST",
data: {request: 'request',},
success: function( data ) {
//Call function to update status on the loading bar
updateBar(data);
}
});
//Update loading bar
function updateBar(data) {
$('progress').attr('value', data);
}
}
function setGo() {
$.ajax({
url : 'ajax.php',
dataType: "html",
type: "POST",
//async: false,
data: {status: 'GO',},
success: function( data ) {}
});
}
$('#start').click(function(event) {
setGo();
setInterval(function() {
getStatus();
}, 1000);
});
This is my php Code
<?php
//Overwrite php execution limit
set_time_limit(120);
if($_POST['status'] = 'GO') {
$number = 5000;
$counter = 0;
for($i=0; $i != $number; $i++) {
$counter++;
sleep(1);
if(isset($_POST['request'])) {
echo $counter;
}
}
}
?>
I tried a lot of different ways and read a lot of posts but somehow nothing worked for me.
Hope someone got an idea.
Take a good look at your "echo $counter;" part in your PHP script, that's in a (5000 times) loop.
After the PHP code is interpreted and executed, the web server sends resulting output to its client, usually in form of a part of the generated web page – for example, PHP code can generate a web page's HTML code
From PHP's wiki page
This basically means that the whole php file will always be executed before returning the output. The loop will be executed 5000 times before returning the output.
Situation:
I'm using an $.ajax() POST to send a request to a php script that inserts about 400,000-500,000 lines into a db. This consistently takes about 3.5 - 4 minutes. (During this time, the request is PENDING).
Problem:
I need some way to show progress on the page. (such as a %). I tried using an $.ajax() in a setInterval that checks every 5 seconds or so, but they seem to build up and all come through when the first (longer) $.ajax() is finished.
Question:
Isn't $.ajax() async by default? Shouldn't this mean requests can be sent out in any order and at any time, and responses should be received in any order and at any time?? Does this even have anything to do with async? Is there a way to periodically send back 'semi-responses' from one request? Or can't I send and receive requests/responses while there is a pending request/response? (see awesome drawing below)
Thanks in advance!!!
multiple requests http://kshaneb.com/reqres.png
Your long-running ajax-call probably opens a session on server, so all next requests are blocked due to a session file lock.
Problem:
PHP writes its session data to a file by default. When a request is made to a PHP script that starts the session (session_start()), this session file is locked. What this means is that if your web page makes numerous requests to PHP scripts, for instance, for loading content via Ajax, each request could be locking the session and preventing the other requests from completing.
The other requests will hang on session_start() until the session file is unlocked. This is especially bad if one of your Ajax requests is relatively long-running.
Solution:
The session file remains locked until the script completes or the session is manually closed. To prevent multiple PHP requests (that need $_SESSION data) from blocking, you can start the session and then close the session. This will unlock the session file and allow the remaining requests to continue running, even before the initial request has completed.
More info here:
http://konrness.com/php5/how-to-prevent-blocking-php-requests/
Hope this helps
$(function ()
{
var statusElement = $("#status");
// this function will run each 1000 ms until stopped with clearInterval()
var i = setInterval(function ()
{
$.ajax(
{
success: function (json)
{
// progress from 1-100
statusElement.text(json.progress + "%");
// when the worker process is done (reached 100%), stop execution
if (json.progress == 100) clearInterval(i);
},
error: function ()
{
// on error, stop execution
clearInterval(i);
}
});
}, 1000);
});
Instead of doing an ajax post you can post to an iframe and have php generate incremental output and send it with the flush command.
// send a hash mark for every 1000 inserts
$a = 0;
while ($rec = getDataForNextInsert()){
$a++;
// do insert
if ($a%1000 == 0) { echo '#'; flush(); }
}
It would also then be possible to poll the contents of the iframe to provide a pretty display for the end user.
I hope this will be useful for you
First of all, you need to disable output buffer in your PHP script
#apache_setenv('no-gzip', 1);
#ini_set('zlib.output_compression', 0);
#ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);
Then you need to echo your progress from the PHP during the process, something like that:
for($i=0;$i < 20;$i++){
echo ($i > 0 ? "#":"").($i/20*100);
sleep(1);
}
Then, in javascript you need to listen for xhr readystate change event and when this happens, just parse the response text and show the progress as you want to.
listening for event:
$.ajaxPrefilter(function( options, _, jqXHR ) {
if ( options.onreadystatechange ) {
var xhrFactory = options.xhr;
options.xhr = function() {
var xhr = xhrFactory.apply( this, arguments );
function handler() {
options.onreadystatechange( xhr, jqXHR );
}
if ( xhr.addEventListener ) {
xhr.addEventListener( "readystatechange", handler, false );
} else {
setTimeout( function() {
var internal = xhr.onreadystatechange;
if ( internal ) {
xhr.onreadystatechange = function() {
handler();
internal.apply( this, arguments );
};
}
}, 0 );
}
return xhr;
};
}
});
and sample of ajax request:
$.ajax({
url: "test.php",
cache: false,
onreadystatechange: function( xhr ) {
res = xhr.responseText.split("#");
$("#id").html(res[res.length-1] + "% done<br/>");
}
}).done(function( data ) {
$("#id").append("all done!</br>");
});
});
tested with jQuery 1.5+
i know this question was probably asked 1 million times, but for the 1.000.001 time :)
i need to call a php function from JavaScript. And i am having a bit of an argument on if ajax will do it.
i don't want to send any data just a ajax call that will call and run that function.
here is what i have so far:
$.post('functions/test.php', function() {
console.log("Hooray, it worked!");
});
is this gonna run the test.php ?
thanks
It definitely runs the test.php, to check it you may do sth. on succes
$.ajax({
type: "POST",
url: "ajax/test.php",
success: function(data) {
alert(data);
}
});
But what's the purpose of sending if no data is send?
Most likely, yes. I can't guarantee it because I don't do jQuery.
This, however, will definitely run it no problems (except versions of IE so old you shouldn't care about them):
var a = new XMLHttpRequest();
a.open("GET","functions/test.php");
a.onreadystatechange = function() {
if( a.readyState == 4) {
if( a.status == 200) {
console.log("Hooray, it worked!");
// optionally, do stuff with a.responseText here
// a.responseText is the content the PHP file outputs, if any
}
else alert("HTTP error "+a.status+" "+a.statusText);
}
}
a.send();
Yes the test.php script will run, and you can grab the output from the test.php script like this (if you want to):
$.post('functions/test.php', function(data) {
//the `data` variable now stores the server response (whatever you output in `test.php`)
console.log("Hooray, it worked!");
});
In JQuery you can do:
$.post('functions/test.php', function(data) {
alert(data);
});
Whatever is returned in test.php will be put into the variable "data"
So you can do any php functions you need to in test.php and send the output back.
I always use
jQuery.ajax("url.php");
I was wondering if it's possible to long poll using $.getJSON and what the proper front and back end logic would be.
I've come up with this so far but haven't tested it yet since I'm pretty sure there is wrong and/or missing logic.
Here is the JS:
function lpOnComplete(data) {
console.log(data);
if (!data.success) {
lpStart();
}
else {
alert("Works!");
}
};
function lpStart() {
$.getJSON("http://path.to.my.URL.php?jsoncall=?", function(data) {
// What happens when no data is returned
// This is more than likely since there
// is no fall back in the PHP.
lpOnComplete(data);
});
};
PHP:
$time = time();
while((time() - $time) < 30) {
// only returns data when it's new.
$data = checkCode();
// What would be the proper way to break out
// and send back $data['success'] = false
// so the JS loop can continue?
if(!empty($data)) {
echo $_GET["jsoncall"] . "(" . json_encode($data) . ")";
break;
}
usleep(25000);
}
From what you've got there, the Javascript is going to make multiple requests to the server and each one is going to spin up that infinite loop, and never go anywhere. I'd suggest something like: js:
$.getJSON("http://my.site/startAsyncWork.php", null, function(data){
waitUntilServerDone(data.token, function(response){
alert("done");
});
});
function waitUntilServerDone(token, doneCallback){
$.getJSON("http://my.site/checkIfWorkIsDone.php", {"token": token}, function(response){
if(response.isDone){
doneCallback(response);
}
else{
setTimeout(function(){
waitUntilServerDone(token, doneCallback);
}, 1000);
}
});
}
I don't know php, so I'm not going to write sample code for that side, but basically, startAsycWork.php makes up a random token that associates to the request. Then it spawns a thread that does all the work needed, and returns the token back to the response.
When the worker thread is done, it writes the results of the work out to a file like token.dat (or puts it in a cache or whatever).
checkIfWorkIsDone.php checks for the existence of token.dat, and returns false if it doesn't exist, or returns the contents if it does.