So I have some code, which checks for whether a one time use discount code exists, and if so, it applies it and then marks it as used in the database. The problem is, it ends up being useable more than once if you spam click it, and then some time maybe 15-20 seconds later it stops being useable.
The relevant javascript component:
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) {
discountAmount += parseFloat(xmlhttp.responseText);
modifyCartOrder();
}
}
xmlhttp.open("GET","forms/jsPromoCode.php?code="+code+"&type="+order_name,true);
xmlhttp.send();
This is processed over in the php file, and when a match is found we echo that amount and then delete the entry
$mysqli->query("DELETE FROM discounts_available WHERE `index`=$index");
The php file is indeed doing what its supposed to. When you click apply code, it is immediately deleted from the database. The problem is, even with the code no longer in the db, you can still apply the code over and over for some amount of time before the js file finally realises there is no entry in the db. Why is this?
You should first check if it exists in DB then only you should proceed with request, it should be very first statement.
If it does not exists you can send response saying code already applied.
You most likely need to lock the table ASAP so no other instances can modify the table concurrently.
http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
I did not get your problem, exactly I am assuming lost of things, so..
//this is triggered on some click, right?
//TODO:- check if button is disabled? you can have some js variable or check button attribute disbled
//TODO:-if its not disaled->{so first disable the button when it is clicked } else do nothing
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) {
discountAmount += parseFloat(xmlhttp.responseText);
// if succefull keep button disabled
// else renable it, so that it can be clicked again.
modifyCartOrder();
}
}
xmlhttp.open("GET","forms/jsPromoCode.php?code="+code+"&type="+order_name,true);
xmlhttp.send();
thers's no syntax problem here in your code its logical,
ajax call is asynchronous call, it does not happen in sequence
1) You clicked
2) Request Sent
3) Request Processed
4) JS is informed : your modifyCartOrder function executed
what I am trying to say here is that, there is no 3 immediately after 2, 3 will take time to start, js has no control over it, whenever php is done it will reply there's no guarantee. so you can repeat 1 again and again, and 2 will keep repeating... and so 3 will...
I hope I understood your problem, and you understood what I am trying to say :)
Problem is : You are sending asynchronous ajax calls from following code :
xmlhttp.open("GET","forms/jsPromoCode.php?code="+code+"&type="+order_name,true);
Solution : as defined , for opening an ajax call , method is :
xmlhttp.open(method,url,async)
So, You have to modify above line as:
xmlhttp.open("GET","forms/jsPromoCode.php?code="+code+"&type="+order_name,false);
Related
I've been racking my brain for a few hours and can't figure out why a string comparison won't work. In the following code, I do a xmlhttp call and get a response text. The PHP file that I get a call IS returning the proper response string "NOAD", and NOAD is being displayed when appropriate in my testing. However, when the call is returned NOAD I want to identify it, however for some reason within the call below xmlhttp.responseText == comparisonText its NOT properly comparing the two. Why does xmlhttp.responseText printout NOAD but I can't use it within the comparator?
function loadXMLAdImage1Doc(currentScenarioTime)
{
var returnText = "Not Here";
var comparisonText = "NOAD";
var xmlhttp;
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)
{
if (xmlhttp.responseText == comparisonText)
{
document.getElementById("AJAXTEST").innerHTML =returnText;
} else {
document.getElementById("AJAXTEST").innerHTML =xmlhttp.responseText;
}
}
}
Okay, thanks Luth for pointing me in the right direction. I solved my problem, but I'm not sure what the problem is within xmlhttp.responseText or user error that caused it.
The return text from my PHP file was placing an unseen character BEFORE the returned string (in testing, I would have figured it was an invisible character after prior to the results but go figure). Theoretically, this shouldn't be happening...my PHP is returning a straightforward string:
..do some MYSQL queries..
$AdLink = mysql_result($result, 0);
if ($AdLink == "") {
echo "NOAD";
} else
{
echo $AdLink;
}
So the PHP file SHOULD be sending a 4 character return screen to the xmlhttp.responseText call named "NOAD". But what was found in measuring the string length was that it was sending a 5 character string back with some invisible character BEFORE "NOAD" that wasn't showing up on the screen - therefore screwing up the comparator. I used the following code to remove the character and it worked perfectly...
returnText = xmlhttp.responseText;
var returnlength = returnText.length;
returnText = returnText.substring(1, returnlength);
I have no idea WHAT the character is, whether its a problem with my PHP code or the xmlhttp.responseText call, but something to be aware of if you're dealing with the call.
Is it possible to have multiple ajax calls on the same page, at the same time to different receiving div tags? I am struggling with finding answer to this.
I have 3 pages. A home page and 2 php pages: status and alert pages echoing the results.
Inside the home page I have 2 divs that get their data changed using ajax.
<div id="statusTable"> </div>
<div id="alertsTable"> </div>
Using setInterval I make 2 requests for new data for the divs at the same time. My problem is that both divs have the same data in them once the call is made - it's as if only one call was made for both.
setInterval
(
function()
{
getAlerts();
getStatus();
},
1000
);
I get this eg.
alerts table // getStatus() call
2 2
2 2
status table // getStatus()
2 2
2 2
instead of
alerts table //getAlerts()
1 1
1 1
status table //getStatus()
2 2
2 2
This is the code:
function loadXMLDoc(url,cfunc)
{
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=cfunc;
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
function getAlerts()
{
loadXMLDoc("alerts.php?update=variable",function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("alertsTable").innerHTML=xmlhttp.responseText;
}
});
}
function getStatus()
{
loadXMLDoc("status.php?update=variable",function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("statusTable").innerHTML=xmlhttp.responseText;
}
});
}
I changed the timer setIntervals so the calls don't overlap the data received in the divs like below
setInterval
(
function()
{
getAlerts();
},
5000
);
setInterval
(
function()
{
getStatus();
},
3000
);
I am hoping there is a way to make a call at the same time and not have to worry about my divs having the same content.
First, AJAX uses HTTP protocol which is stateless. If you can't be sure which answer reached first unless you tag them yourself in the response body.
Maybe the 2 reaches first and set, as receiving only one packet results in readyState change and drops other.
Your xmlhttp variable is defined globally. So by that, the packet with 1 inside is overloaded by packet with 2 inside. Try using var xmlhttp while defining it in your getAlert and getStatus functions and provide it to your loadXMLDoc function as a parameter.
Second, make sure whether the results should be different or not. Maybe it is just a coincident that both values are the same.
You need to decalre the xmlhttp variable locally in loadXMLDoc()
function loadXMLDoc(url,cfunc)
{
var xmlhttp;
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=cfunc;
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
Without doing this, the xmlhttp value that is improperly declared in the function "leaks" into the global scope, meaning that you end up overwriting the values with whichever is called second (including the url value set on the object). You in essence introduce a race condition into your code due to asynchronous nature of the calls.
The race condition and the xmlhttp being global are the problems here.
What ever came last is overwriting the data written in the divs. Solve it by making xmlhttp variable
local as per suggestions and tagging the response body.
function loadXMLDoc(xmlhttp,url,cfunc)
{
xmlhttp.onreadystatechange=cfunc;
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
function getAlerts()
{
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
loadXMLDoc(xmlhttp,"alerts.php?update=variable",function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200 && xmlhttp.responseText.indexOf("unique key") != -1)
{
//change div which matches unique key
}
});
}
Credit: #Mike Brant and #Cunning
Before people like me want to continue and use more ajax calls check out
how browsers handle and process multiple ajax calls:
How many concurrent AJAX (XmlHttpRequest) requests are allowed in popular browsers?
http://sgdev-blog.blogspot.com/2014/01/maximum-concurrent-connection-to-same.html
I'm trying to execute a block of code when my XMLHttpRequest reaches state 2. The reason why I want it to be in state 2 is that I don't want the user to wait for a response of the server( I would like to redirect the user at this point).
var xmlhttp;
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 == 2) {
window.location.href = urlFromPreviousAjaxcall;
}
}
xmlhttp.open("POST", "url", true);
xmlhttp.send();
However the block of code inside the if(xmlhttp.readyState == 2) will only be called as soon as the server is done processing the call. This part has to be executed as soon as the call is made( without the waiting from the server).
In the documentation I found that state 2 is reached as soon as the call is send. However that is not the case.
Update:
the call I am trying to make involves calling a Api on the server( this takes time to complete). For the client it doesn't matter what happens to the call.The only thing I want is that the call is executed. So basicly I'm trying to gain speed here.
I know that as soon as I redirect the user, the code will stop running. However the call to the server should have been made(and send away).
What am I missing or doing wrong?
Thanks you all for your help.
I found the solution:
[HttpPost]
public void methode(String parameter,String parameter)
{
Task.Factory.StartNew<string>(() => RunTask(accessToken, parameter, parameter));
}
private string RunTask(String parameter, String parameter)
{
try
{
// Code to execute here
return "Done!";
}
catch (Exception e)
{
return "Error: " + e.Message;
}
}
At the server I started a Task. In this task I execute the long procces. It still takes a brief moment before the server returns the call to the user.
When debuggin ( in visual studio) you can see that the task is running without the presents of the user.
Note : all sessions are gone at the moment I redirected the user to an other page.
i am using a google map api to get location. i have used the below function onchange of address field. it is working properly onchange. i have used same function on submit in the same form to checking the function once again while submitting using a onsubmit attribute. but while submitting i cant able to get answer from this ajax because of the that return by using this return true the form submit with pout getting answer.
please any one find a solution for this
function validatePlaceForm(){
var frm = document.frmOncampus;
var oncampusAddress = frm.oncampusAddress.value;
var xmlhttp;
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("my_div").innerHTML=''
var result =xmlhttp.responseText;
//alert(result);
var both =result.split("|");
frm.oncampusLatitude.value=both[0];
frm.oncampusLongtitude.value=both[1];
}
}
var url='latlog.php?address='+oncampusAddress;
xmlhttp.open("GET",url,true);
xmlhttp.send();
return true;
}
Unfortunately this will never work because the way you're using the XHR there is asynchronous:
xmlhttp.open("GET",url,true); // true means asynchronous
As the call is asynchronous the result of the function will have no result on the running of the Ajax request.
If you want to continue with using this function just change this last parameter to false, i.e.
xmlhttp.open("GET", url, false); // will now be synchronous
You also won't need a onreadystatechange handler now. Bear in mind that this will obviously make the XHR call synchronous on your onchange event too; maybe customise the function to accept a flag for is_synchronous or something.
You might also want to consider adding a timestamp onto your requests so that the browser does not cache the response.
Change the return value from true to false and call this function like this:
onsubmit="return validatePlaceForm();"
This should do the trick.
Check for the response coming from AJAX. If response is blank then return false, otherwise return true.
I am using a simple "live search" script that displays the results from a MySQL database as the user types into a text box. It works perfectly fine if the Javascript is pointing to a completely separate page but I need it to point to the same page. Unfortunately when I try and do this the page is duplicated within itself as the results are generated.
This works as expected:
Document called: "test.php" containing JavaScript below and test2.php containing the PHP code
xmlhttp.open("GET","test2.php?livesearch="+str,true);
xmlhttp.send();
This creates a page within a page:
Document called: "test.php" containing both the JavaScript and PHP code below
xmlhttp.open("GET","?livesearch="+str,true);
xmlhttp.send();
I understand that it's because it is opening itself in a loop but I'm not sure what I am supposed to change in the code to avoid this. Any help would be greatly appreciated as I haven't found much help via Google.
Here is all my code:
Javascript
function showResult(str)
{
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("livesearch").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","&livesearch="+str,true);
xmlhttp.send();
}
PHP Code
if(isset($_GET['livesearch'])) {liveSearch();}
function liveSearch() {
$q=$_GET["livesearch"];
$sqlQuery = "SELECT * FROM something WHERE something LIKE '%" . $q . "%' ;
etc etc etc
}
Why would you want the code to point to itself? Seems logical to have a web service that would return only the content that is needed. It is not like you have to duplicate the code, just make some common method that spits out the content in the full page or in the web service.
If you need to call the same page, you can always use a regular expression to rip out the content that you need instead of replacing the whole page.