Sorry if this topic already exists, but I couldn't find the solution. I have some calculations processed on server side. These calculations consists of several steps. I would like a response for each executed step. For instance, there are 5 steps in a task, and server must send me 5 responses:
Step 1 is executed
Step 2 is executed
Step 3 is executed
...etc
I read a lot of forums and blogs, but I can't solve this problem. In my case I think it is better to use long polling in comet. I wrote a simple example of my task (posted below); it doesn't work. This task has button which starts the counter (from 1 to 11 with sleep 1 sec), then Ajax sends a requests. The server must give the accumulated text ($q_msg), clear this variable, and continue to accumulate another counts. But instead of this, server accumulates everything without any responses and at the end response all in an answer. So, where is my fault? Please, assist me.
HTML:
<script type="text/javascript">
var request;
function createXMLRequest() {
request = new XMLHttpRequest();
return request;
}
//start counter
function comet_btnStart() {
document.getElementById('count1').innerHTML = "";
createXMLRequest();
var param = "btnStart=pusk";
request.open("GET", "counter.php?" + param, true);
request.onreadystatechange = comet_response;
request.send(null);
}
//get values
var q = "";
function comet() {
createXMLRequest();
var param = "q=" + q;
request.open("GET", "counter.php?" + param, true);
request.onreadystatechange = comet_response;
request.send(null);
}
function comet_response() {
if (request.readyState === 4)
{
if (request.status === 200)
{
if (request.responseText !== null)
{
var text = request.responseText;
if (text === "end") document.getElementById('count1').innerHTML += "<br/>Task is executed";
else
{
var result = text.split(",");
q = result[result.length-1];
document.getElementById('count1').innerHTML += "<br/>" + request.responseText;
setTimeout(comet, 2000);
}
}
else document.getElementById('count1').innerHTML += "<br/>No response";
}
else document.getElementById('count1').innerHTML += "<br/>Invalid connection";
}
}
</script>
</head>
<body>
<div>
Click button to start counter: <input type="button" value="Начать" name="btnStart" id="btnStart" onclick="comet_btnStart()" /><br/><br/>
Counts:<br/> <span id='count1' style='color: #246499; font-weight: bold'></span>
</div>
</body>
PHP:
<?php
if (isset($_GET['btnStart']))
{
$q_msg = "";
$q = 0;
logic::counter();
echo $q_msg;
$q_msg = "";
}
if (isset($_GET['q']))
{
$lastq = $_GET['q'];
global $q;
if ($lastq < $q)
{
echo $q_msg;
$q_msg = "";
}
else echo "end";
}
class logic
{
static function counter()
{
global $q;
while ($q <= 10)
{
sleep(1);
$q++;
global $q_msg;
if (strlen($q_msg) > 0) $q_msg .= ", " . $q;
else $q_msg = $q;
//just for debugging
echo $q_msg; //why server doesn't send data???
}
}
}
$msc=microtime(true);
//executing code
$msc=microtime(true)-$msc;
echo $msc.' seconds'; // in seconds
echo ($msc*1000).' milliseconds'; // in millseconds
i dont know if this is what you are looking for. But if i understsand correct this is what you are looking for. You can read more here How to get the execution time of a MySQL query from PHP?
Credit to Christian
Related
I recently notice that I have a duplicate line on the table, when the device is spinning or calling someone on this davay at the time of pressing the 'save' button. On the lines of UserRealTime I see that the interval is a duplicate of 5-6 milliseconds.
How to avoid duplicates using javascript or jQuery. For example, check the connection of the device to the Internet?
ajax.php
<?php
if (isset($_GET['d1']) && isset($_GET['d2']))
{
$conn=connSQL();
$query = "insert into doorname(d1, d2, UserRealTime) values ('".$_GET['d1']."','".$_GET['d2']."', getdate())";
$rs=$conn->execute($query);
$rs->Close();
$conn->Close();
}
?>
JavaScript
<script>
var httpObject = null;
function getHTTPObject()
{
if (window.ActiveXObject)
{
return new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest)
{
return new XMLHttpRequest();
}
else
{
return null;
}
}
function Inter()
{
httpObject = getHTTPObject();
if (httpObject != null)
{
var d1=document.getElementById('d1').value;
var d2=document.getElementById('d2').value;
if (d1=="" || d2=="")
{
alert("sorry!!!");
}
else
{
httpObject.open("GET", "ajax.php?d1="+d1+"&d2="+d2, true);
httpObject.send(null);
httpObject.onreadystatechange = InterSet;
}
}
}
function InterSet()
{
if(httpObject.readyState == 4)
{
var data=httpObject.responseText;
alert("Good!!!");
}
}
</script>
This way of approach it is not a suggested practice. However, just to work around the problem here is one way of handling general duplicate DB entries.
Generate one random Token on the client side for every successful server side insert. Discard the Token on client side once the server confirms the successful insert. Following is an example:
1) Generate a random Token on the client side, like so
Generate random string/characters in JavaScript
var tokenOnClientSide = makeid();
2) Attach the generated Token to Ajax Params:
httpObject.open("GET", "ajax.php?d1="+d1+"&d2="+d2+"&token="+token, true);
3) Server side: Look if the Token already exists
<?php
if (isset($_GET['d1']) && isset($_GET['d2']) && isset($_GET['token']))
{
$query = sprintf("SELECT * FROM token_table WHERE token = '%s'", $_GET['token']);
$rs=$conn->execute($query);
if (mysql_num_rows($res) == 0) {
// carry on with insert and return success message
.....
// now store the token permanently
$query = "insert into token_table(token, time_of_exec) values ('".$_GET['token']."', getdate())";
$rs=$conn->execute($query);
}
4) Finally, unset the global token on client side
tokenOnClientSide = "";
Hope that one gets a basic idea of handling duplicates.
I have some issues retrieving info from python and try to show the data in a html page
I get the date from a python script (data.py)
import cx_Oracle
import json
lst_proveedores=[{}]
conn_str = 'user/pass#database'
conn = cx_Oracle.connect(conn_str)
c = conn.cursor()
c.execute('select id, name from provider')
for row in c:
record1 = {"id":row[0], "name":row[1]}
lst_proveedores.append(record1)
json_string = json.dumps(lst_proveedores)
print json_string
conn.close()
I try to parse the info with AJAX in a html page
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
function ajax_get_json(){
var results = document.getElementById("results");
var hr = new XMLHttpRequest();
hr.open("GET", "prov1.py", true);
hr.responseType = "JSON";
hr.setRequestHeader("Content-Type", "application/json", true);
hr.onreadystatechange = function() {
if(hr.readyState == 4 && hr.status == 200) {
var data = JSON.parse(hr.responseText);
results.innerHTML = "";
for(var obj in data){
results.innerHTML += data[obj].id+" is "+data[obj].nombre+"<hr />";
}
}
}
hr.send(null);
results.innerHTML = "requesting...";
}
</script>
</head>
<body>
<div id="results"></div>
<script type="text/javascript">ajax_get_json();</script>
</body>
</html>
but doesn't work
I setup apache to execute python scripts and work with very simple scripts, but doesn't work when I retrieve data from the database
How can I show the data in a html page?
Or what language or framework may I can use to show the data
Any advice
I am desperate
Thanks in advance
First of all, you should try visit your python files in browser. If you can't see json print on page, there're problems in your server or python code.
If it works, that may be something wrong in your Ajax request.
You can use jQuery or zepto.js to help. They contain a method of Ajax: $.ajax.
You can visit: http://zeptojs.com
And search "$.ajax" on the page for help; )
===============================================================
try this:
//var data = JSON.parse(hr.responseText);
var data = JSON.parse(hr.response);
===============================================================
and this is my onreadystatechange function code, use it if it helps:
ajaxObject.onreadystatechange = function(){
//console.info('[Ajax request process] url:' + url +'; readyState:' + ajaxObject.readyState + '; status:' + ajaxObject.status);
if (ajaxObject.readyState == 4 && ((ajaxObject.status >= 200 && ajaxObject.status < 300) || ajaxObject.status == 304)){
var result = null;
switch (dataType){
case 'text':
result = ajaxObject.responseText;
break;
case 'xml':
result = ajaxObject.responseXML;
break;
case 'json':
default:
result = ajaxObject.response ? JSON.parse(ajaxObject.response) : null;
break;
}
if (typeof(success) == 'function'){
success(result,url);
}
}else if (ajaxObject.readyState > 1 && !((ajaxObject.status >= 200 && ajaxObject.status < 300) || ajaxObject.status == 304)){
console.warn('[Ajax request fail] url:' + url +'; readyState:' + ajaxObject.readyState + '; status:' + ajaxObject.status);
if (typeof(error) === 'function' && errorCallbackCount == 0){error(url);errorCallbackCount++;}
return false;
}
}
My requirement is to make multiple xml request and to store the data in an array so that if i get say for example 4000 records I can display 40 records in a page and can do pagination. So if i goto page2 I can get the data from the array instead of making the xml request again.
Currently I am using a php array variable to store large amount of data and on click a button javascript function will call the same php page again using ajax request through query string. The problem is that the query string can't hold large arrays.
Here is my code -
Passing php array to javascript variable
echo '<script type="text/javascript">/* <![CDATA[ */';
echo 'var allProd = '.json_encode($allProd);
echo '/* ]]> */</script>';
Using form calling javascript function through button click
<form id="new_page" name="new_page" method="post" action="" >
<td> Jump to page <input name="neggPage" id="neggPage" class="pageText" style="height:20px; width:40px"/></td>
<input type="hidden" name="hideProd" value="<?php echo htmlentities(serialize($allProd)); ?>" />
<td><input type="Submit" name="neggBut" value="Go" class="pageButton" onClick="get_results(document.getElementById('neggPage').value, <?php echo $sInd; ?>, <?php echo $rndTot; ?>, <?php echo $totEnt; ?>, allProd);">
Total pages <?php echo $rndTot; ?></td>
<td height="40"> </td>
</tr></table>
</form>
Javascript function
<script>
function get_results(PageNo, SelIndex, totPage, totEnt, allProd)
{
var allProd1 = '';
for (i=0; i < allProd.length; i++)
{
allProd1 += '&q[' + i + ']=' + encodeURIComponent(JSON.stringify(allProd[i]));
}
if (PageNo > totPage || isNaN(PageNo))
{
alert ('Please enter the available pages');
}
else
{
var neggProd = sessionStorage.getItem('Product1');
var cntryCode = sessionStorage.getItem('Cntry');
var sortType;
var ordType;
if (SelIndex == 0) {sortType = 'bestmatch';}
else if (SelIndex == 1) {sortType = 'bestseller';}
else if (SelIndex == 2) {
sortType = 'pricehigh';
ordType = 'dsc';
}
else if (SelIndex == 3) {
sortType = 'pricelow';
ordType = 'asc';
}
document.getElementById("sl_api").innerHTML="";
document.getElementById("sl_api1").setAttribute("style","background: url('KartEazy/loading.gif') #edeeee no-repeat center center; background-size:20px 20px;");
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("sl_api").innerHTML= xmlhttp.responseText;
}
}
xmlhttp.open("GET",'KartEazy/Skimlinks/Skimlinks.php?PageNum=' + PageNo + '&neggProd=' + neggProd + '&cntryCode=' + cntryCode + '&sortType=' + sortType + '&ordType=' + ordType + '&totEnt=' + totEnt + allProd1, true);
xmlhttp.send();
setInterval(function() {
document.getElementById("sl_api1").setAttribute("style","background: #edeeee;")},4500);
}
}
</script>
In the same page now I am trying to get the array
if(isset($_REQUEST['q']))
{
$totEnt = $_REQUEST['q'];
}
I tried using hidden form variable but even $_POST also not accepting large arrays. Could any of you please give me a solution or suggestion. It will be very helpful for me.
Even storing the data in database or session variable will not solve my requirement. Because if I use database I can't retrieve data for multiple queries and even php session variable will be overwritten if the user uses multiple tabs for the same url.
I was in a similar situation where I was passing several MEG of data from Javascript to PHP.
I don't have the code with me, so I can only give you a p-code solution, but it will give you the idea.
// JavaScript:
var bigstring = "...."; the data to pass
var chunkSize = 100*1024;
// http://stackoverflow.com/questions/7033639/javascript-split-large-string-in-n-size-chunks
var chunks = splitString(bigstring);
var chunkIdx = -1; // Prime the pump
function sendNextChunk() {
chunkIdx++;
if (chunkIdx < chunks.length) {
// Your AJAX call here
var data = {
piece: chunkIdx
ofpieces: chunks.length;
}
// set your onsuccess method to call
// sendNextChunk again
}
}
sendNextChunk(); // start it.
Now, for your PHP code:
// Read in each chunk, and the piece number.
// The way I've got the code written, then come in sequentional order
// so open up a temporary file and append the data.
// when piece === ofpieces
// you have the whole file and you can then process it.
I am trying to implement a simple "global" counter that updates based on every user that clicks the button on their browsers button. For example, if you go to the website and click the button, I will see the counter increase on my side if I'm on the same website. I sought to do this with long polling, but am facing some issues. Mainly the server variable is not coming back as I think it should.
The server:
package main
import (
"net/http"
"log"
"io"
"io/ioutil"
)
var messages chan string = make(chan string, 100)
var counter = 0
func PushHandler(w http.ResponseWriter, req *http.Request) {
body, err := ioutil.ReadAll(req.Body)
if err != nil {
w.WriteHeader(400)
}
counter += 1
messages <- string(counter)
}
func PollResponse(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, <-messages)
}
func main() {
http.Handle("/", http.FileServer(http.Dir("./")))
http.HandleFunc("/poll", PollResponse)
http.HandleFunc("/push", PushHandler)
err := http.ListenAndServe(":8005", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
The client:
<html>
<script language=javascript>
function longpoll(url, callback) {
var req = new XMLHttpRequest ();
req.open ('GET', url, true);
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4) {
if (req.status == 200) {
callback(req.responseText);
longpoll(url, callback);
} else {
alert ("long-poll connection lost");
}
}
};
req.send(null);
}
function recv(msg) {
var box = document.getElementById("counter");
box.value += msg + "\n";
}
function send() {
var box = document.getElementById("counter");
var req = new XMLHttpRequest ();
req.open ('POST', "/push?rcpt=", true);
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4) {
if (req.status == 200) {
} else {
alert ("failed to send!");
}
}
};
req.send("hi")
//box.innerHTML += "test" ;
}
</script>
<body onload="longpoll('/poll', recv);">
<h1> Long-Poll Chat Demo </h1>
<p id="counter"></p>
<button onclick="send()" id="test">Test Button</button>
</body>
</html>
The counter variable is not coming back from the server for some reason. I believe I am changing the state every time the button is clicked and so the longpolling function should get the newly updated counter variable. If you have any suggestions, please let me know!
I see two issues in you program:
1. In the server:
messages <- string(counter)
You should use "strconv" package
messages <- strconv.Itoa(counter)
string(0) will return something like []byte{0} not a "0"
2. In your client:
function recv(msg) {
var box = document.getElementById("counter");
box.value += msg + "\n";
}
Should be:
function recv(msg) {
var box = document.getElementById("counter");
box.innerHTML += msg + "\n";
}
I don't think the p element have value property
Building a chat app and I am trying to fetch all logged in user into a div with ID name "chat_members". But nothing shows up in the div and I have verified that the xml file structure is correct but the javascript i'm using alongside ajax isn't just working.
I think the problem is around the area of the code where I'm trying to spool out the xml data in the for loop.
XML data sample:
<member>
<user id="1">Ken Sam</user>
<user id="2">Andy James</user>
</member>
Javascript
<script language="javascript">
// JavaScript Document
var getMember = XmlHttpRequestObject();
var lastMsg = 0;
var mTimer;
function startChat() {
getOnlineMembers();
}
// Checking if XMLHttpRequest object exist in user browser
function XmlHttpRequestObject(){
if(window.XMLHttpRequest){
return new XMLHttpRequest();
}
else if(window.ActiveXObject){
return new ActiveXObject("Microsoft.XMLHTTP");
} else{
//alert("Status: Unable to launch Chat Object. Consider upgrading your browser.");
document.getElementById("ajax_status").innerHTML = "Status: Unable to launch Chat Object. Consider upgrading your browser.";
}
}
function getOnlineMembers(){
if(getMember.readyState == 4 || getMember.readyState == 0){
getMember.open("GET", "get_chat.php?get_member", true);
getMember.onreadystatechange = memberReceivedHandler;
getMember.send(null);
}else{
// if the connection is busy, try again after one second
setTimeout('getOnlineMembers()', 1000);
}
}
function memberReceivedHandler(){
if(getMember.readyState == 4){
if(getMember.status == 200){
var chat_members_div = document.getElementById('chat_members');
var xmldoc = getMember.responseXML;
var members_nodes = xmldoc.getElementsByTagName("member");
var n_members = members_nodes.length;
for (i = 0; i < n_members; i++) {
chat_members_div.innerHTML += '<p>' + members_nodes[i].childNodes.nodeValue + '</p>';
chat_members_div.scrollTop = chat_members_div.scrollHeight;
}
mTimer = setTimeout('getOnlineMembers();',2000); //Refresh our chat members in 2 seconds
}
}
}
</script>
HTML page
<body onLoad="javascript:startChat();">
<!--- START: Div displaying all online members --->
<div id="chat_members">
</div>
<!---END: Div displaying all online members --->
</body>
I'm new to ajax and would really appreciate getting help with this.
Thanks!
To troubleshoot this:
-- Use an HTTP analyzer like HTTP Fiddler. Take a look at the communication -- is your page calling the server and getting the code that you want back, correctly, and not some type of HTTP error?
-- Check your IF statements, and make sure they're bracketed correctly. When I see:
if(getMember.readyState == 4 || getMember.readyState == 0){
I see confusion. It should be:
if( (getMember.readyState == 4) || (getMember.readyState == 0)){
It might not make a difference, but it's good to be absolutely sure.
-- Put some kind of check in your javascript clauses after the IF to make sure program flow is executing properly. If you don't have a debugger, just stick an alert box in there.
You must send the xmlhttp request before checking the response status:
function getOnlineMembers(){
getMember.open("GET", "get_chat.php?get_member", true);
getMember.onreadystatechange = memberReceivedHandler;
getMember.timeout = 1000; //set timeout for xmlhttp request
getMember.ontimeout = memberTimeoutHandler;
getMember.send(null);
}
function memberTimeoutHandler(){
getMember.abort(); //abort the timedout xmlhttprequest
setTimeout(function(){getOnlineMembers()}, 2000);
}
function memberReceivedHandler(){
if(getMember.readyState == 4 && getMember.status == 200){
var chat_members_div = document.getElementById('chat_members');
var xmldoc = getMember.responseXML;
var members_nodes = xmldoc.documentElement.getElementsByTagName("member");
var n_members = members_nodes.length;
for (i = 0; i < n_members; i++) {
chat_members_div.innerHTML += '<p>' + members_nodes[i].childNodes.nodeValue + '</p>';
chat_members_div.scrollTop = chat_members_div.scrollHeight;
}
mTimer = setTimeout('getOnlineMembers();',2000); //Refresh our chat members in 2 seconds
}
}
To prevent caching response you can try:
getMember.open("GET", "get_chat.php?get_member&t=" + Math.random(), true);
Check the responseXML is not empty by:
console.log(responseXML);
Also you might need to select the root node of the xml response before selecting childNodes:
var members_nodes = xmldoc.documentElement.getElementsByTagName("member"); //documentElement selects the root node of the xml document
hope this helps