I realise this question was already asked on StackOverflow but the answer is mostly focused on jQuery.
How do I return the response from an asynchronous call?
I have a JavaScript function that allows people on the website to vote. However they can only vote once a day. So I am trying to call another JS function which is doing an AJAX call. This in turn calls a PHP page, which is doing a query in the database to check whether the caller voted in the last 24H.
function can_vote(user_id)
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "rating.php?&user_id=" + user_id, true);
xmlhttp.send();
var result = true;
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
console.log("answer: " + xmlhttp.responseText);
return (xmlhttp.responseText == "false") ? false : true; // doesn't work
}
}
}
function rating(user_id)
{
if (can_vote(user_id) == false)
{
// display error message
...
return false;
}
...
}
This doesn't work for the reasons explained in the link I provided earlier. I tried to follow the suggestions suggested in this link but I can't make it work (I can only use JavaScript no jQuery). I tried to implement a callback system:
can_vote(callback, user_id)
{
...
xmlhttp.onreadystatechange=function()
{
// if we can a positive answer from the rating.php
// then call the callback function
callback();
}
}
function rating(user_id)
{
var result = false;
can_vote(function() {
result = true;
}, user_id);
console.log(result); // always false
...
}
But while the mechanism works, it doesn't update the variable true, which seems to be "local" to the callback function.
It feels like I am close to the solution, but can't go any further. Passing a variable by reference to the function doesn't work in JS, so I have explored all options I can think of.
Could someone please help and suggest a fix/solution (using JavaScript only)?
EDIT 1:
As suggested earlier, while the answer in How do I return the response from an asynchronous call? is very thorough and informative, it answers the question using jQuery not JavaScript.
EDIT 2 and ANSWER:
I can't answer my own question for whatever reason, but fair enough, because in fact I should have thought twice before asking it. So thanks for all answers.
- Apologies, it is indeed a duplicate of the question linked above
- Egg Vans suggested to rethink the problem. This is indeed one way. In fact it's possible in the PHP page creating the rating system, to actually call a PHP function when the user votes. My system requires the user to click on "stars" to vote. Thus, I could set the
onclick
callback to a PHP function rather than a JS function and bypass AJAX all together. - however the reason I can't do this is because finding out the number of stars chosen by the user requires some calls to DOM functions.
Now, while I consider myself as an okay programmer, the problem is that in this particular situation, I completely overlooked the code. The original question contains the correct answer for "processing" the result of an AJAX call from within a JS function. So what I have overlooked is that in fact, the actual result of the AJAX call will be "processed" in the callback function. So for example in my case if the user can vote, then I should execute some code within this call back function, and if he/she can't vote, I should execute some other code in the same call back function. In other words:
function can_vote(callback, user_id)
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "rating.php?user=" + user_id, false);
xmlhttp.send();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
// pass the result to the callback function and process this result accordingly
callback(xmlhttpx.responseText);
}
}
}
function star_rating(user_id)
{
...
can_vote(function(result)
{
if (result == false)
{
// you can't vote display error message
}
else
{
// you can vote do your stuff here, find out what's the rating from the user
// add it to the db, and update the current rate yet using another
// AJAX call.
}
}, user_id);
// any code you put after this line will be processed likely before the AJAX call returns
...
}
Thanks again everything for your patience. Hope though that this concrete example will help others.