I have a php server file and an HTML client file, the HTML file send ajax requests to the server to retrieve data every 500 ms, this although works as expected it's causing high usage of memory and CPU on the client's device.
PHP
if(isset($_POST['id']) && $_POST['id'] != '' )
{
$id = $_POST['id'];
$select = $con->prepare("SELECT * FROM data WHERE id=?");
$select->bind_param('s', $id);
$select->execute();
$result = $select->get_result();
while($row = $result->fetch_assoc())
{
echo $row['column 1'] . "\t" . $row['column 2'] . "\n";
}
}
AJAX
function send(){
var formdata = new FormData(),
id = document.getElementById('id').value;
formdata.append('id', id);
var xhr = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('post', 'server.php', true);
xhr.send(formdata);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
console.log(xhr.responseText);
}
}
}
setInterval(function(){send()}, 500);
I would like to find an alternative solution to ajax, instead of sending numerous requests to the server and retrieving same data most of the time, it would be much more efficient if the server can interact with the client on data change or update.
I can't use PHP Socket or HttpRequest methods as they are not installed on my hosting server and I'm not sure if the later works. The only way I can think of is using SESSIONS.
According to this PHP server store all users sessions on the same directory on the server, therefore it may be possible to change sessions variables for a particular user directly on the file. The problem however is the data in those files are serialized and I'm not sure how to de-serialize the data and re-serialize them and then save the new data!
Even if I was able to find a way to store updates on the session file, I still need to use setInterval to listen to the session's variable change every 500ms although it's not ideal but it would be much better than using XMLHttpRequest in terms of memory and CPU usage.
So what's the best way to do this? any help would be much appreciated.
UPDATE:
I realized that SESSION wont work because it can be read only by the server not the client, therefore i have to send ajax request to the server to get the variables which i was trying to avoid.
I tried long polling but i had many problems with it, flush and ob_flush() doesn't work on my server and i can't change the ini settings. When trying the infinite loop i can't get it to break on data change:
if(isset($_GET['size']) && $_GET['size'] != '')
{
$size = (int)$_GET['size'];
$txt = "logs/logs.txt";
$newsize = (int)filesize($txt);
while(true) {
if($newsize !== $size) {
$data = array( "size" => filesize($txt), "content" => file_get_contents($txt));
echo json_encode($data);
break;
}
else{
$newsize = (int)filesize($txt);
usleep(400000);
}
}
}
it keeps going on and on, even if the logs.txt size increase it won't break! how can I make it break and echo data on size increase?
UPDATE 2:
It turned out the php cache the filesize when calling filesize() method therefore the above loop will run indefinitely, the solution for that is to use clearstatcache() method which will clear the stored cache of the file size allowing the loop to break on filesize changes.
Okay, after many tests and long research i came to the conclusion that PHP server can never interact with a specified client directly unless the client send a request to the server first.
The only reliable solution i found is to use infinite loop which will only break on data change, this will reduce the frequency of ajax requests to the server considerably, hence increasing the performance and decreasing the usage of the Memory and CPU on the client's device, here how it goes:
PHP 1 (Handles data update or new data insert to database):
$process = $_POST['process'];
$log = "/logs/logs.txt";
if($process == 'update'){
//execute mysqli update command and update table.
$str = "Update on " . date('d/m/Y - H:i:s') . "\n";//add some text to the logs file (can be anything just to increase the logs.text size)
file_put_content($log, $str, FILE_APPEND);//FILE_APPEND add string to the end of the file instead or replacing it's content
}
else if($process == 'insert'){
//execute mysqli insert command and add new data to table.
$str = "Added new data on" . date('d/m/Y - H:i:s') . "\n";
file_put_content($log, $str, FILE_APPEND);
}
The above code will insert/update data, create file log.txt if not existed and add additional text to it on each request. log.txt will be used later in the infinite loop "below" and would break the loop when it's size change.
PHP 2 (handles reading data requests):
if(isset($_POST['id']) && $_POST['id'] != '' && isset($_POST['size']) && $_POST['size'] != '')
{
$id = (string)$_POST['id'];
$init_size = (int)$_POST['count'];
$size = file_exists('logs/logs.txt') ? (int)filesize('logs/logs.txt') : 0;//$size is logs.txt size or 0 if logs.txt doesn't exist(not created yet).
$select = $con->prepare("SELECT * FROM data WHERE id=?");
$select->bind_param('s', $id);
while(true){ //while(true) will loop indefinitely because condition true is always met
if($init_size !== $size){
$select->execute();
$result = $select->get_result();
while($row = $result->fetch_assoc())
{
$data['rows'][] = array(
"column 1" => $row['column 1'],
"column 2" => $row['column 2'],
);
}
$data['size'] = $size;
echo json_encode($data);
break; //break the loop when condition ($init_size != $size) is met which indicates that database has been updated or new data has been added to it.
}
else{
clearstatcache(); //clears the chached filesize of log.txt
$size = file_exists('logs/logs.txt') ? (int)filesize('logs/logs.txt') : 0;
usleep(100000) //sleep for 100 ms
}
}
}
AJAX:
var size = 0; //declares global variable size and set it's initial value to 0
function send(s){
var formdata = new FormData(),
id = document.getElementById('id').value;
formdata.append('id', id);
formdata.append('size', s);
var xhr = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('post', 'server.php', true);
xhr.timeout = 25000; //set timeout on xmlhttprequest to 25 sec, some servers has short execution tiemout, in my case it's 27 sec so i set the value to 25 sec.
xhr.send(formdata);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
var data = JSON.parse(xhr.responseText);
size = data.size;
console.log(data.rows);
setTimeout(function(){send(size)}, 100); //re-initiate the request after receiving data
}
}
xhr.ontimeout = function(){
xhr.abort(); //abort the timed out xmlhttp request
setTimeout(function(){send(size)}, 100);
}
send(size);
This is not the ideal solution but it reduced my xmlhttp requests from 2/sec to as low as 1/25 sec, hope that someone will be able to come up with a better solution.
Before we had capabilities to use sockets in browsers, we used Long polling. The basic idea is that instead of the browser making requests at regular intervals, the browser will make a request to the server, but the server won't respond until there is something worthwhile to share back to the browser. That means the request could be left open for 10ms or for hours.
After the server responds with something, it is then the browser's job to make a new ajax request. This way, there is always a line open to the server.
Refer to this question for more information.
Answering the part of your question about directly editing a session...
To directly manipulate the session of a user, I will assume you know and can track any user's session ID (perhaps in your database on sign in).
When you need to edit a user's session directly on the server:
Retrieve user's last known session from the database.
Call session_close() to close the current session (if there is one).
Call `session_name($sessionId)' with the session ID.
Call session_open() to open that session. $_SESSION should be populated with the session data. You will not need to unserialize anything.
Make your edits to the session.
Call session_close() to reserialize the data.
Alternatively, you could directly open the session file, unserialize() it, edit the data, and re-serialize() manually.
You could create an ajax request to an php script which will only return data if there is any new data. As long there is no new data the script keeps running in a loop until there is.
I think the anwser for this question today is to use Websocket read about it. without request the server you can get data if there's something change it into server
see link
you can use SSE or Websocket to achieve this.
Related
I'm playing around with AJAX long-polling and trying to read/update a simple counter (number) value in an MySQL cell by clicking on a button.
The PHP creates an infinite while loop and is checking if the value in the according cell has been modified (MySQL "current_timestamp", UNIX). If it has and the current_timestamp value is bigger then the timestamp the AJAX call was made, it's breaking the loop and sending the updated value and the updated current_timestamp to the client. The AJAX processes the data.
The Problem: It works but after a while I get a 503 error. I guess it's obviously the while loop or other open connections through multiple windows in other browsers (for testing).
PHP-File text.php:
// Connect to database
$con = mysql_connect('XX', 'XX', 'XX');
if (!$con)
{
die('Error' . mysql_error());
}
mysql_select_db('X', $con);
// Get data
$query = mysqli_query("SELECT counter_value, last_modified FROM content WHERE X = 'X' ORDER BY X DESC");
// Start infinite loop
set_time_limit(0);
while (true)
{
// The timestamp of the last ajax call = the last modified timestamp
$last_ajax_call = $_GET['timestamp'];
clearstatcache();
// Get the value of the counter and the last modified timestamp
while($row = mysql_fetch_array($query))
{
$counter_value = $row['counter_value'];
$last_modified= strtotime($row['last_modified']);
}
// If the time of the last modified timestamp is bigger/later than the last ajax call
if ($last_modified > $last_ajax_call)
{
$result = array(
'counter_value' => $counter_value,
'timestamp' => $last_modified
);
$json = json_encode($result);
echo $json;
break;
// If not, try again in 3 seconds
} else
{
sleep(3);
continue;
}
}
// Close database
mysql_close($con);
AJAX Part in js-File:
function getContent()
{
// get timestamp of last modified stored in attribute. The initial/first timestamp attribute is set beforehand.
var timestamp = $('#timestamp').attr('data-timestamp');
$.ajax(
{
type: 'GET',
url: 'test.php',
async: true,
cache: false,
data: {timestamp:timestamp},
success: function(data){
var obj = jQuery.parseJSON(data);
$("#counter").text(obj.counter_value);
$("#timestamp").attr("data-timestamp", obj.timestamp);
getContent();
}
}
);
}
getContent();
So the result is a 503 error which goes away after ca. 10 Minutes and it's working again.
(Any typos/formatting might be the result of cleaning up the code.)
I just started learning PHP and JS, so there might be a few newbie mistakes or weird lines in there, please be nice. Any advice on optimising the code is very appreciated!
It dies because PHP doesn't work the way you think it does.
You have intentionally put an infinite loop into your php in the assumption it will make your code keep looping around and rechecking the next GET request on each loop.
The reality is that the code is executed once for each request, and until execution of the code completes the server doesn't respond.
AJAX long polling requires no special handling in php, it's just an AJAX request in a loop. You might want to include a slight delay in your AJAX code otherwise your server will be hammered with requests.
To be honest this isn't what long polling is for, the idea of it is to update pages without any user interaction to display unread message notifications etc.
If you want to monitor user events like button clicks then bind your AJAX function to the clicking of the button.
A POS software overwrites the orders in a text fie. I am trying to make a Kitchen Display which shows the orders.
My php script reads from that text file...
A comparision is made after every 1 second using sleep(1); to check if a new order has arrived.
<?php
$f1 = fopen("G:/order.txt", 'r');
$firstLine1 = fgets($f1);
fclose($f1);
sleep(1);
$f2 = fopen("G:/order.txt", 'r');
$firstLine2 = fgets($f2);
fclose($f2);
if($firstLine1 != $firstLine2) {
$fh = fopen("G:/order.txt", "r");
echo "<div>";
while ($line = fgets($fh)) {
echo ($line);
}
fclose($fh);
echo "</div>";
}
?>
And using Ajax I run that script every 1 mini second.
<script>
function loadDoc(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
$("p").before(this.responseText);
}
};
xhttp.open("GET", "order.php", true);
xhttp.send();
}
window.setInterval(function(){
loadDoc()
}, 1);
</script>
The problem is that that around 50 Divs are created for every new order where it should be just 1.
1 Div per order.
Please help me I'm messed up.
I think this will work better. Since you're making repeated ajax calls to run the same script, it doesn't make much sense to read repeatedly from the file during each run. Plus your comparison doesn't make any reference to what happened last time the script ran, which, combined with the insane frequency of ajax requests, is resulting in endless duplicate results.
Instead, compare the order ID retrieved on each run to the one retrieved on the previous run. Also, you need to increase the interval between requests, otherwise you'll swamp your server, and also run the risk of concurrency problems where your next request tries to begin before the previous one finishes (don't forget that ajax calls run asynchronously).
PHP
<?php
session_start(); //enable sessions
$f1 = fopen("G:/order.txt", 'r');
$firstLine = fgets($f1);
//check whether a previous order ID has been stored during this session.
if (isset($_SESSION["lastOrderID"])) {
//if the order ID in the file is the same as the last stored one in the session, don't send any data to the client
if ($firstLine == $_SESSION["lastOrderID"])
{
echo "";
fclose($f1);
die();
}
}
echo "<div>";
echo $firstLine;
while ($line = fgets($f1)) {
echo ($line);
}
echo "</div>";
//store the last order ID in the session
$_SESSION["lastOrderID"] = $firstLine;
fclose($f1);
JavaScript
<script>
function loadDoc(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
$("p").before(this.responseText);
}
};
xhttp.open("GET", "order.php", true);
xhttp.send();
}
window.setInterval(loadDoc, 10000); //refresh every 10 seconds. You can decrease the interval if you like, but don't make it so short that it regularly starts another request before the previous one has completed. You can use your browser's network tools to see how the long requests normally take, and use that to help you decide on a suitable value. Leave some headroom for the occasional slowdown.
</script>
Bear in mind that this will only work for the duration of the session - i.e. normally just for as long as the browser window is open, or until the session times out. You can google how to increase the session timeout if necessary. If you require anything more persistent than this (i.e. to remember the last Order ID between sessions) then you should use another text file, or a database in order to record this information, instead of the session.
I'd also like to re-iterate here my concern that your POS software seems overly simplistic, at least based on the details given in the question, and that for audit and other fairly obvious purposes, it might make sense to persist historical records of all orders using a database, instead of over-writing a text file each time a new order is entered.
Ok so, some context. My college started doing some "learning on the job" type classes, and it's becoming a pain because it's like an internship without any sort of capacitation. Just my luck I was assigned a project I'm barely prepared for.
Right now I've been asked to join together an old Jamit Job Board with the login system of the place. Basically verify first if the user exist in the test database, then check if they exist in the local jobboard database. The problem is I don't have any ajax experience since it's not a topic we have touched in my classes. Sad, I know.
I was trying using cURL but was told by the supervisor it wouldn't work.
public function validar_request($Username,$Password) {
$Username = ($_REQUEST['username']);
$Password = md5(stripslashes($_REQUEST['password']));
function httpGet($url,p){
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$output=curl_exec($ch);
curl_close($ch);
return $output;
}
$respuesta1 = httpGet("http://www01pruebasweb.fod.ac.cr/upe/templates/interfaces/ConexionFramework.php?procedimiento=nombreUsuarioExiste&username=".$Username);
The URL will return a 1 is the user exists in the testing database, 0 if not. I was thinking on doing a series of If else that if response = 1, then proceed to login, else donĀ“t since its like a 3 step verification process. First if the user exists, then if the password exists, and lastly if both tables in both databases match.
Response I get in the browser looks like this.
If the user usuario_01 exists then I should get a one. The idea me and a teammate had was to use curl to store the 1 into a variable in php and compare it but it's not working. Specially with the mess that is, for me, the other code for logging of Jamit. I mainly have experience with Java, not web development so as you can understand I'm very overwelmed.
I was trying to contact support from Jamit to see if they had any help, but they aren't active since 2013. Though not sure how much help they would be.
Not sure if necessary but part of the code for logging of Jamit is this
function validate_candidate_login($login_page='') {
global $login_output;
if ($login_output) { echo $login_output; return; } // this function was buffered
if ($login_page=='') {
$login_page = JB_BASE_HTTP_PATH.JB_CANDIDATE_FOLDER."index.php";
}
global $label;
$Username = ($_REQUEST['username']);
$Password = md5(stripslashes($_REQUEST['password']));
$sql = "Select * From users Where Username='".jb_escape_sql($Username)."'";
$result = JB_mysql_query($sql);
// init $row
if (mysql_num_rows($result)==0) {
$row = array();
} else {
$row = mysql_fetch_array($result, MYSQL_ASSOC);
}
JBPLUG_do_callback('val_can_set_pass', $Password); // Note for Plugin authors: Password is passed by refrence. Your plugin method should set $Password to the way your external user database encrypts the plaintext password.. eg $Password = md5($_REQUEST['password']); for phpBB
JBPLUG_do_callback('val_can_login', $row); // Note for Plugin authors: $row argument is passed by reference, which is the row of your users table. The row is populated if username/pass are valid, $row['Username'] and $row['Password'] are set for the code below and should come from your external database. You may also set $row['Validated'] too
if ((!$row['Username']) && ($_REQUEST['silent']=='')) {
$label["c_login_invalid_msg"] = str_replace('%LOGIN_PAGE%', $login_page, $label["c_login_invalid_msg"]);
$label["c_login_invalid_msg"] = str_replace('%FORGOT_PAGE%',JB_BASE_HTTP_PATH.JB_CANDIDATE_FOLDER."forgot.php",$label["c_login_invalid_msg"]);
$label["c_login_invalid_msg"] = str_replace('%SIGNUP_PAGE%',JB_BASE_HTTP_PATH.JB_CANDIDATE_FOLDER."signup.php",$label["c_login_invalid_msg"]);
echo '<p style="text-align:center; ">'.$label["c_login_invalid_msg"]."</p>";
} else {
if ($row['Validated']=="0") {
$label["c_login_notvalidated"] = str_replace('%BASE_HTTP_PATH%', JB_BASE_HTTP_PATH, $label["c_login_notvalidated"]);
echo '<p style="text-align:center; ">'.$label["c_login_notvalidated"].'</p>';
} else {
if (($Password === $row['Password']) || ((JB_ALLOW_ADMIN_LOGIN=='YES')&&(JB_ADMIN_PASSWORD===$_REQUEST['password']))) {
JBPLUG_do_callback('val_can_login_sync', $row); // Note for Plugin authors: Initialize $row with a Jamit user row. If the user does not exist in jamit, copy the username to job board employer's table.
JBPLUG_do_callback('val_can_login_set_session', $row); // Note for Plugin authors: set session variables for your external database (successful login)
JB_set_candidate_session($row); // set session for the candidate
$label['c_login_welcome'] = str_replace ("%FNAME%", JB_escape_html($_SESSION['JB_FirstName']), ($label['c_login_welcome']));
$label['c_login_welcome'] = str_replace ("%LNAME%", JB_escape_html($_SESSION['JB_LastName']), ($label['c_login_welcome']));
$label['c_login_welcome'] = str_replace ("%USERNAME%", JB_escape_html($_SESSION['JB_Username']), ($label['c_login_welcome']));
if (isset($_REQUEST['page'])) {
$label['c_login_welcome'] = preg_replace('/index\.php/i', htmlentities($_REQUEST['page']), $label['c_login_welcome']);
}
if ($_REQUEST['silent']=='') {
echo '<p style="text-align:center; ">'.$label["c_login_welcome"].'</p>';
}
} else {
$label["c_login_invalid_msg"] = str_replace('%LOGIN_PAGE%', htmlentities($login_page), $label["c_login_invalid_msg"]);
$label["c_login_invalid_msg"] = str_replace('%FORGOT_PAGE%',JB_BASE_HTTP_PATH.JB_CANDIDATE_FOLDER."forgot.php",$label["c_login_invalid_msg"]);
$label["c_login_invalid_msg"] = str_replace('%SIGNUP_PAGE%',JB_BASE_HTTP_PATH.JB_CANDIDATE_FOLDER."signup.php",$label["c_login_invalid_msg"]);
if (strpos($login_page, 'apply_iframe.php')!==false) {
$label["c_login_invalid_msg"] = str_replace('_parent', '_self', $label["c_login_invalid_msg"]);
}
echo '<div style="text-align:center;">'.$label["c_login_invalid_msg"].'</div>';
}
}
}
}
Ok cool - per the comments you're looking to get started with AJAX (Asynchronous Javascript And XML). I would highly recommend linking jQuery to your html page to get started - it will make AJAX calls MUCH easier.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
Awesome, now we have jQuery loaded, which allows you to make an ajax call with a simple function.
So now we need to get values from the browser to the server. How do we do that? There are 2 approaches I would recommend:
1 - Use JSON (Javascript Object Notation) to send data to the server with key/value pairs. PHP is great for working with JSON.
2 - Serialize a form using jQueries $(formElement).serialize() function. This turns forms into key/value pairs and you can then receive the data using PHPs $_POST['keyOfFormField']
So I'm going to assume you're going with the JSON approach, which is always preferable in my opinion.
If you're unfamiliar with javascript, JSON format looks like this:
var jsonExample = {'Im a key': 'and im its value'};
This is how you represent an object literal in javascript, and we can send these to the server and store them in an associative array in PHP.
So, on to the ajax call. I will leave it up to you to research ways of getting your data into JSON format. It should be really simple.
In jQuery, an AJAX call looks like this:
$.ajax({
url: 'urlOfServerFile.php',
async: true,
data: JSON.stringify({'Im a key': 'Im its value'}),
type: "POST",
datatype: 'json',
success: function (json) {
json = JSON.parse(json);
//The server sent you back some data, do something with it!
},
error: function () {
alert("Please check your internet connection and try again");
}
});
So what is this doing?
$.ajax() is a function. In jQuery, you basically get access to this really awesome object, which is the jQuery object (it's also represented by the $ sign). So, $.ajax() is the same thing as saying jQuery.ajax()
The $.ajax() function takes an object as an argument. Remember that the {} is how we encapsulate an object in javascript.
The documentation for this object can be found here: http://api.jquery.com/jquery.ajax/
Basically, we need to tell the $.ajax() function a few things:
url - where are we sending this request?
async - will this request be sent asynchronously?
data - what data are we sending to the server?
type - what type of HTTP request are we sending this data in (POST, PUT, GET, etc)
datatype - what type of data are we sending?
success - what do we do if the request is successful?
error - what do we do if the request fails?
Well, at this point we've successfully sent data from browser to server asynchronously. How do we handle this in PHP? Here's how:
$input = json_decode(file_get_contents('php://input'), true);
This variable, $input is now an associative array with all of the JSON key/value pairs that we sent over. So, now we can store some of those values in variables like this:
$randomVariable = $input['im a key'];
I hope this post will get you started with AJAX. Once you get the hang of it, it's a really intuitive technology that will make your applications WAY better.
Is it possible to use SSE to send POST data to PHP like in Ajax?
I've been using AJAX now for quite a while with bad results in long-polling technicues. I have also been thinking about WebSockets, but it seems a bit redundant.
No, SSE cannot send any data to the server.
You can still use SSE to read data in real time and use AJAX to upload any data (you might need a shared database to pass information between AJAX-receiving processes and SSE-sending one).
You can send data via GET.
e.g.
name=john&name=lea
This is a simple script that sends to server number of iteration and the server return progress using SSE.
This Project consists of two files (index.php and ssedemo.php).
index.php contain a text box and a button. the textbox suppose to contain the number of iteration of the loop in ssedemo.php
<h2>Server Sent Event Test</h2>
<form>
<label>Process Duration</label>
<input type="text" id="progVal">
<input type="button" value="Get Messages" onclick="updateProgress()"/>
</form>
<div id="container">
</div>
updateProgress
function updateProgress() {
var input = $('#progVal').val();
var evtSource = new EventSource("ssedemo.php?duration=" + encodeURIComponent(input));
evtSource.addEventListener("progress", function (e) {
var obj = JSON.parse(e.data);
$('#container').html(obj.progress);
if( parseInt(obj.progress) == 100){
evtSource.close();
}
}, false);
}
this function get the content of the textbox using jQuery and then create an eventSource. The EventSource() constructor takes one or two arguments. The first specifies the URL to which to connect. The second specifies the settings, if any, in the form of an EventSourceInit dictionary.
You can pass what you want by adding it to URL as you do with GET.
"ssedemo.php?duration=" + encodeURIComponent(input)
In the server side, you have to set header type and disable cache according to W3C recommendation
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
then you get the data using $_GET as usual.
$TotalNo = $_GET['duration'];
for ($i = 1; $i <= $TotalNo; $i++) {
updateProgress($i, $TotalNo);
sleep(1);
}
function updateProgress($currentVal, $totalNo) {
$completionPrecentage = $currentVal / $totalNo * 100;
echo "event: progress\n";
echo 'data: {"progress": "' . $completionPrecentage . '"}';
echo "\n\n";
ob_flush();
flush();
}
if you want to send array you can refer to this
The EventSource API does not support POST method, however that does not mean that you cannot use SSE with POST. You just cannot use the EventSource API.
There are alternative implementations however. One example is sse.js which allows you to specify a payload, and also headers if you need. sse.js should be a drop-in replacement for EventSource, eg:
var source = new SSE("get_message.php");
source.onmessage=function(event)
{
document.getElementById("message-window").innerHTML+=event.data + "<br>";
};
In order to use a POST method, you just need to specify a payload, eg:
var source = new SSE("get_message.php", {payload: 'Hello World'});
And, since it is a fully compatible polyfill, you can probably do this:
EventSource = SSE;
var source = new EventSource("get_message.php", {payload: 'Hello World'});
source.onmessage=function(event)
{
document.getElementById("message-window").innerHTML+=event.data + "<br>";
};
I've got a page that seems to be in full working order, but I'm having major performance issues (think 30 second delay occasionally from these calls) from what I assume is throwing too many individual POST requests to the server.
Am I right in thinking that there's some way of doing it all in one call and that doing so would improve performance, and what's the easiest way of doing it? Perhaps my use of eval() is part of the problem - or maybe my webhost is just shit.
function startCheckAchs(){
//hide the loading alert
$(document).ajaxStop(function(){
$(this).unbind("ajaxStop");
popup('loadingAlert');
});
//load lifeTimeBaked
lifeTimeBaked = loadAch("lifetimebaked");
loadAch("ach_started", "#achStarted", "achstarted");
loadAch("ach_round1", "#achRound1", "achround1");
loadAch("ach_round2", "#achRound2", "achround2");
loadAch("ach_round3", "#achRound3", "achround3");
if( rewards == 1) {
loadAch("ach_baked100", "#achBaked100", "achbaked100");
loadAch("ach_baked500", "#achBaked500", "achbaked500");
loadAch("ach_baked1000", "#achBaked1000", "achbaked1000");
loadAch("ach_nobread", "#achNoBread", "achnobread");
loadAch("ach_nodough", "#achNoDough", "achnodough");
loadAch("ach_noflour", "#achNoFlour", "achnoflour");
loadAch("ach_allach", "#achAllAch", "achallach");
}
}
function loadAch(ach, achDiv, achVar){
$.ajax({
type: "POST",
url: "scripts/loadach.php",
data: {"achievement" : ach},
dataType: "text",
success: function(result){
if ( achDiv && achVar && result == 1){
$(achDiv).show();
eval(achVar + " = 1");
return result;
} else {
return result;
}
}
});
}
Loadach.php:
$achievement=trim($_POST['achievement']);
$user = $_SESSION['userid'];
$query = "SELECT $achievement FROM breadusers WHERE userid='$user'";
$link =#mysql_query($query);
if(!$link){
die('Could not query:' . mysql_error());
}
echo mysql_result($link, 0);
?>
You are currently loading achievements individually, while you should be doing something like:
<?php
$query = "SELECT ach_started, ach_round1 FROM breadusers WHERE userid='$user'";
$link = mysql_query($query);
$results = mysql_fetch_assoc($link);
echo json_encode($results);
?>
Then, in your javascript code, parse the JSON response (setting dataType: "json" should work), loop over the returned object (has keys such as ach_started, ach_round1, etc etc), and show/hide divs as needed.
Unfortunately you are going to have to redesign that.
SQL queries are slow.
Lots of requests make things slow.
See if you can group all of the data for a user in your database. That way you can make one select for all of the data you need.
You could use a multi-dimensional array and fill it with the data needed, send the array with ajax to the php code, and then you could loop through the array in the php code and echo back the desired results.
This way you would only be making 1 ajax call each time but still get the same results. might be faster this way but i have not tested this. =)
Most browsers have a limit on the number of concurrent server requests they can handle.
If you're using sessions, you'll also find that the server can only process a single request for each session at a time, because the session file is locked by each request, and subsequent requests must wait for it to be unlocked either when the first request finishes, or when a session_write_close() is issued by the executing request.