Fasten this Ajax response - javascript

The following Ajax works , but it takes a while just to notify user on the client side that the username is already taken. Is there any ways to fasten this respons, or it's just normal behavior of Ajax.
Client :
<title>Choose a username</title>
<style>
#targetDiv {
background-color: #FF9999;
width: 40%;
}
</style>
<script type = "text/javascript">
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
}
function getData(dataSource)
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", dataSource);
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
if(XMLHttpRequestObject.responseText == "taken"){
var targetDiv = document.getElementById("targetDiv");
targetDiv.innerHTML = "<div>That username is taken.</div>";
}
}
}
XMLHttpRequestObject.send(null);
}
}
function checkUsername(keyEvent)
{
keyEvent = (keyEvent) ? keyEvent: window.event;
input = (keyEvent.target) ? keyEvent.target : keyEvent.srcElement;
if (keyEvent.type == "keyup") {
var targetDiv = document.getElementById("targetDiv");
targetDiv.innerHTML = "<div></div>";
if (input.value) {
getData("check.php?name=" +input.value);
}
}
}
</script>
</head>
<body>
<H1>Choose a username</H1>
Enter your new username <input id = "textField" type = "text"
name = "textField" onkeyup = "checkUsername(event)">
<div id = "targetDiv"><div></div></div>
</body>
</html>
Server
<?php
if ($_GET["name"] == "steve"){
echo "taken";
}
else {
echo "ok";
}
?>

Your question is "how to fasten the response".
The response is send by your server over the net.
The time taken for the net transfer will always vary.
But you can try to get faster responses of your server by optimizing the configuration of the webserver and PHP. You can test the response behavior of your server with a benchmark tool like abor siege.
And then tweak, test, compare results, repeat-until-satisfied.
A request to the server is a request to the server. No matter, if it is done by a browser via ajax or the benchmark tool.
For instance, upgrading to PHP 5.6 and enabling and tuning the opcache, gives quite a performance boost, when compared to let's say PHP 5.3. There a lot of optimizations possible. The question is too broad to go into detail.
When looking at the client-side JS: this is plain-vanilla JS.
Not much room for improvements. The only thing which comes to my mind is
to change the xhrObject for IE from "Microsoft.XMLHTTP, which is really old, to new ActiveXObject("Msxml2.XMLHTTP.6.0"); (and maybe add a fallback to new ActiveXObject("Msxml2.XMLHTTP.3.0");).

It will always take some time to get the respond from the server, you can tune up your server to be faster but you will always have a delay.
However what you can do is show a loading splash while you are connecting with the server.

You can also try storing usernames in Memcached as it will reduce the time taken for sql query.

Related

Duplicate JavaScript and php problems

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.

ajax responseText contains php source code

I am trying to make a ajax call and validate a input html field. But, instead of getting simple echo message. I am getting complete source code in responseText.
JavaScript
function checkUsername() {
document.getElementById("username").className = "thinking";
usernameRequest = createRequest();
if (usernameRequest == null)
alert("Unable to create request");
else {
var theName = document.getElementById("username").value;
var username = escape(theName);
var url= "checkName.php?username=" + username;
usernameRequest.onreadystatechange = showUsernameStatus;
usernameRequest.open("GET", url, true);
usernameRequest.send(null);
}
}
function showUsernameStatus() {
alert(usernameRequest.responseText);
if (usernameRequest.readyState == 4)
{
if (usernameRequest.status == 200) {
if (usernameRequest.responseText == "okay") {
document.getElementById("username").className = "approved";
document.getElementById("register").disabled = false;
}
else {
document.getElementById("username").className = "denied";
document.getElementById("username").focus();
document.getElementById("username").select();
document.getElementById("register").disabled = true;
}
}
}
}
checkName.php
<?php
$takenUsernames = array('bill', 'ted');
sleep(2);
if (!in_array($_REQUEST['username'],$takenUsernames )) {
echo 'okay';
} else {
echo 'denied';
?>
Previously, I tried to integrate PHP into tomcat, but I was advice it was not a good practice. TRIAL TO INTEGRATE PHP
What I can make out of this situation is that Tomcat is not parsing PHP file and instead it is returning the source code. I believe there should be a means for me to let tomcat parse php files and send the right response.
I have also tried with simple php code, with one statment <?php echo 'HELLO'; ?> and I still get the source code.
Thanks in advance.
NOTE : I do not know php, I am working an example from HEAD FIRST AJAX
you need to install PHP for Tomcat & set its path to compile it.see the below link for php configuration settings.
http://php-java-bridge.sourceforge.net/doc/tomcat6.php
http://www.studytrails.com/blog/php-on-a-java-app-server-apache-tomcat-using-quercus/

fetching xml data into a div via ajax and javascript

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

History API, refresh and bookmark

pushState doesn't make a request, it just changes the url and stores a new history entry. Thinking about this concept, it's impossible to refresh or bookmark because the server will always do a request. A server-side solution is needed.
After several hours searching, I have found a solution, every single call must be redirect to index.php to let PHP handle the request.
rewrite ^/(.*)$ /index.php?page=$1 last
I don't know exactly how this file should be to let a website refresh or bookmark a page. Can somebody help me ? I made an example to help clarify.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<title>History API</title>
<script>
function ajax (url, callback) {
var conection = new XMLHttpRequest ();
conection.open ("GET", url, true);
conection.setRequestHeader ("X-Requested-With", "XMLHttpRequest");
conection.send (null);
conection.onreadystatechange = function () {
if (conection.readyState === 4) {
if (conection.status === 200) {
callback (conection.responseText);
}
else if (conection.status === 404) {
alert ("Page not found !");
}
else {
alert ("Error !");
}
}
}
}
window.addEventListener ("popstate", function (event) {
var state = event.state;
if (state) {
document.getElementById ("content").innerHTML = state["content"];
}
});
document.addEventListener ("DOMContentLoaded", function () {
var content = document.getElementById ("content");
var menu = document.getElementById ("menu");
menu.addEventListener ("click", function (event) {
var target = event.target;
if (target.nodeName === "A") {
ajax (target.href, function (result) {
history.pushState ({"content": result}, target.innerHTML, target.href);
content.innerHTML = result;
});
event.preventDefault ();
}
});
});
</script>
<style>
body {
width: 400px;
}
div {
border: 1px solid black;
padding: 10px;
}
</style>
</head>
<body>
<div id = "menu">
Page 1
Page 2
</div>
<div id = "content"></div>
</body>
</html>
index.php
<?php
isset ($_GET["page"]) or exit ("Error !");
$page = $_GET["page"];
// Ajax request
if (isset ($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower ($_SERVER["HTTP_X_REQUESTED_WITH"]) === "xmlhttprequest") {
if (file_exists ($page)) {
require_once ($page);
}
else {
header ("HTTP/1.1 404 Not Found");
}
}
else {
require_once ("index.html");
}
?>
page1.html
Hello, I'm the Page 1. It's nice to meet you.
page2.html
Hi brother. I'm page 2.
Clicking (ok)
Refresh (fails)
First of all you should really not use a GET parameter as input for a _require_once_. Really. Not. Use at least a simple whitelist of allowed names for pages and only include and output mapped files (or files with those whitelisted names).
Now to your history API problem. Pushing things obviously seems to work for you so all that is missing is probably a simple ondomready event that reads the current URL and loads the content via AJAX or from existing history entries. The same whitelist approach should be used there. Also try to not fall into the trap of DOMXSS by using unvalidated input (the URL) as input for your javascript and DOM operations.

Is it possible to ping a server from Javascript?

I'm making a web app that requires that I check to see if remote servers are online or not. When I run it from the command line, my page load goes up to a full 60s (for 8 entries, it will scale linearly with more).
I decided to go the route of pinging on the user's end. This way, I can load the page and just have them wait for the "server is online" data while browsing my content.
If anyone has the answer to the above question, or if they know a solution to keep my page loads fast, I'd definitely appreciate it.
I have found someone that accomplishes this with a very clever usage of the native Image object.
From their source, this is the main function (it has dependences on other parts of the source but you get the idea).
function Pinger_ping(ip, callback) {
if(!this.inUse) {
this.inUse = true;
this.callback = callback
this.ip = ip;
var _that = this;
this.img = new Image();
this.img.onload = function() {_that.good();};
this.img.onerror = function() {_that.good();};
this.start = new Date().getTime();
this.img.src = "http://" + ip;
this.timer = setTimeout(function() { _that.bad();}, 1500);
}
}
This works on all types of servers that I've tested (web servers, ftp servers, and game servers). It also works with ports. If anyone encounters a use case that fails, please post in the comments and I will update my answer.
Update: Previous link has been removed. If anyone finds or implements the above, please comment and I'll add it into the answer.
Update 2: #trante was nice enough to provide a jsFiddle.
http://jsfiddle.net/GSSCD/203/
Update 3: #Jonathon created a GitHub repo with the implementation.
https://github.com/jdfreder/pingjs
Update 4: It looks as if this implementation is no longer reliable. People are also reporting that Chrome no longer supports it all, throwing a net::ERR_NAME_NOT_RESOLVED error. If someone can verify an alternate solution I will put that as the accepted answer.
Ping is ICMP, but if there is any open TCP port on the remote server it could be achieved like this:
function ping(host, port, pong) {
var started = new Date().getTime();
var http = new XMLHttpRequest();
http.open("GET", "http://" + host + ":" + port, /*async*/true);
http.onreadystatechange = function() {
if (http.readyState == 4) {
var ended = new Date().getTime();
var milliseconds = ended - started;
if (pong != null) {
pong(milliseconds);
}
}
};
try {
http.send(null);
} catch(exception) {
// this is expected
}
}
you can try this:
put ping.html on the server with or without any content, on the javascript do same as below:
<script>
function ping(){
$.ajax({
url: 'ping.html',
success: function(result){
alert('reply');
},
error: function(result){
alert('timeout/error');
}
});
}
</script>
You can't directly "ping" in javascript.
There may be a few other ways:
Ajax
Using a java applet with isReachable
Writing a serverside script which pings and using AJAX to communicate to your serversidescript
You might also be able to ping in flash (actionscript)
You can't do regular ping in browser Javascript, but you can find out if remote server is alive by for example loading an image from the remote server. If loading fails -> server down.
You can even calculate the loading time by using onload-event. Here's an example how to use onload event.
Pitching in with a websocket solution...
function ping(ip, isUp, isDown) {
var ws = new WebSocket("ws://" + ip);
ws.onerror = function(e){
isUp();
ws = null;
};
setTimeout(function() {
if(ws != null) {
ws.close();
ws = null;
isDown();
}
},2000);
}
Update: this solution does not work anymore on major browsers, since the onerror callback is executed even if the host is a non-existent IP address.
To keep your requests fast, cache the server side results of the ping and update the ping file or database every couple of minutes(or however accurate you want it to be). You can use cron to run a shell command with your 8 pings and write the output into a file, the webserver will include this file into your view.
The problem with standard pings is they're ICMP, which a lot of places don't let through for security and traffic reasons. That might explain the failure.
Ruby prior to 1.9 had a TCP-based ping.rb, which will run with Ruby 1.9+. All you have to do is copy it from the 1.8.7 installation to somewhere else. I just confirmed that it would run by pinging my home router.
There are many crazy answers here and especially about CORS -
You could do an http HEAD request (like GET but without payload).
See https://ochronus.com/http-head-request-good-uses/
It does NOT need a preflight check, the confusion is because of an old version of the specification, see
Why does a cross-origin HEAD request need a preflight check?
So you could use the answer above which is using the jQuery library (didn't say it) but with
type: 'HEAD'
--->
<script>
function ping(){
$.ajax({
url: 'ping.html',
type: 'HEAD',
success: function(result){
alert('reply');
},
error: function(result){
alert('timeout/error');
}
});
}
</script>
Off course you can also use vanilla js or dojo or whatever ...
If what you are trying to see is whether the server "exists", you can use the following:
function isValidURL(url) {
var encodedURL = encodeURIComponent(url);
var isValid = false;
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
type: "get",
async: false,
dataType: "json",
success: function(data) {
isValid = data.query.results != null;
},
error: function(){
isValid = false;
}
});
return isValid;
}
This will return a true/false indication whether the server exists.
If you want response time, a slight modification will do:
function ping(url) {
var encodedURL = encodeURIComponent(url);
var startDate = new Date();
var endDate = null;
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
type: "get",
async: false,
dataType: "json",
success: function(data) {
if (data.query.results != null) {
endDate = new Date();
} else {
endDate = null;
}
},
error: function(){
endDate = null;
}
});
if (endDate == null) {
throw "Not responsive...";
}
return endDate.getTime() - startDate.getTime();
}
The usage is then trivial:
var isValid = isValidURL("http://example.com");
alert(isValid ? "Valid URL!!!" : "Damn...");
Or:
var responseInMillis = ping("example.com");
alert(responseInMillis);
const ping = (url, timeout = 6000) => {
return new Promise((resolve, reject) => {
const urlRule = new RegExp('(https?|ftp|file)://[-A-Za-z0-9+&##/%?=~_|!:,.;]+[-A-Za-z0-9+&##/%=~_|]');
if (!urlRule.test(url)) reject('invalid url');
try {
fetch(url)
.then(() => resolve(true))
.catch(() => resolve(false));
setTimeout(() => {
resolve(false);
}, timeout);
} catch (e) {
reject(e);
}
});
};
use like this:
ping('https://stackoverflow.com/')
.then(res=>console.log(res))
.catch(e=>console.log(e))
I don't know what version of Ruby you're running, but have you tried implementing ping for ruby instead of javascript? http://raa.ruby-lang.org/project/net-ping/
let webSite = 'https://google.com/'
https.get(webSite, function (res) {
// If you get here, you have a response.
// If you want, you can check the status code here to verify that it's `200` or some other `2xx`.
console.log(webSite + ' ' + res.statusCode)
}).on('error', function(e) {
// Here, an error occurred. Check `e` for the error.
console.log(e.code)
});;
if you run this with node it would console log 200 as long as google is not down.
You can run the DOS ping.exe command from javaScript using the folowing:
function ping(ip)
{
var input = "";
var WshShell = new ActiveXObject("WScript.Shell");
var oExec = WshShell.Exec("c:/windows/system32/ping.exe " + ip);
while (!oExec.StdOut.AtEndOfStream)
{
input += oExec.StdOut.ReadLine() + "<br />";
}
return input;
}
Is this what was asked for, or am i missing something?
just replace
file_get_contents
with
$ip = $_SERVER['xxx.xxx.xxx.xxx'];
exec("ping -n 4 $ip 2>&1", $output, $retval);
if ($retval != 0) {
echo "no!";
}
else{
echo "yes!";
}
It might be a lot easier than all that. If you want your page to load then check on the availability or content of some foreign page to trigger other web page activity, you could do it using only javascript and php like this.
yourpage.php
<?php
if (isset($_GET['urlget'])){
if ($_GET['urlget']!=''){
$foreignpage= file_get_contents('http://www.foreignpage.html');
// you could also use curl for more fancy internet queries or if http wrappers aren't active in your php.ini
// parse $foreignpage for data that indicates your page should proceed
echo $foreignpage; // or a portion of it as you parsed
exit(); // this is very important otherwise you'll get the contents of your own page returned back to you on each call
}
}
?>
<html>
mypage html content
...
<script>
var stopmelater= setInterval("getforeignurl('?urlget=doesntmatter')", 2000);
function getforeignurl(url){
var handle= browserspec();
handle.open('GET', url, false);
handle.send();
var returnedPageContents= handle.responseText;
// parse page contents for what your looking and trigger javascript events accordingly.
// use handle.open('GET', url, true) to allow javascript to continue executing. must provide a callback function to accept the page contents with handle.onreadystatechange()
}
function browserspec(){
if (window.XMLHttpRequest){
return new XMLHttpRequest();
}else{
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
</script>
That should do it.
The triggered javascript should include clearInterval(stopmelater)
Let me know if that works for you
Jerry
You could try using PHP in your web page...something like this:
<html><body>
<form method="post" name="pingform" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<h1>Host to ping:</h1>
<input type="text" name="tgt_host" value='<?php echo $_POST['tgt_host']; ?>'><br>
<input type="submit" name="submit" value="Submit" >
</form></body>
</html>
<?php
$tgt_host = $_POST['tgt_host'];
$output = shell_exec('ping -c 10 '. $tgt_host.');
echo "<html><body style=\"background-color:#0080c0\">
<script type=\"text/javascript\" language=\"javascript\">alert(\"Ping Results: " . $output . ".\");</script>
</body></html>";
?>
This is not tested so it may have typos etc...but I am confident it would work. Could be improved too...

Categories

Resources