I have written a jQuery / JS function which "runs a php query".
function runQuery(op){
if(op.type == "edit"){
var b = false;
if(op.id != "" && (op.fromSong || op.toSong || op.when || op.comment)){
$.post("processor.php", { id: op.id, type: "edit", fromSong: op.fromSong, toSong: op.toSong, when: op.when, comment: op.comment }, function(data){
if(data == true){
console.log(true);
b = true;
}else{
console.log(false);
b = false;
}
});
}
return b;
}
I want it to return true of false depending on what the server answers. I'm sure that the php script is working correctly and returning true or false correctly. But every time i run the function the console.log() outputs the correct value, unlike the variable b. It seems to alway be false. What am I doing wrong?
Since any .ajax() call ($.post is just a wrapper to $.ajax) runs asyncronously, your variable b will always return false. Best thing to "workaround" this is to pass in another callback:
function runQuery(op, callback){
if(op.type == "edit"){
if(op.id != "" && (op.fromSong || op.toSong || op.when || op.comment)){
$.post("processor.php", { id: op.id, type: "edit", fromSong: op.fromSong, toSong: op.toSong, when: op.when, comment: op.comment }, function(data){
if(data == true){
console.log(true);
callback.apply(this, [data]);
}else{
console.log(false);
callback.apply(this, [data]);
}
});
}
}
runQuery({
type: 'edit',
}, function(data) {
alert(data);
});
yes it is wrong.
$.post is done asynchronously, so b is set in the call back but returned before you reach the callback.
you should use $.ajax instead with method:"POST", and async: false
However it could be better to have a deisgn when you use the value of b in the callback only because async: false can freeze your browser.
Your function will return before the asynchronous request to the server has completed. Before you ask, it is both impractical and undesierable to make the call synchronous so that you can return true/false from your function. You might consider supplying a callback argument or arguments to your function:
function runQuery(op, success, failure){
// ...
if(data == true){
success();
}else{
failure();
}
// ...
}
runQuery('edit',
function () { alert('success!'); },
function () { alert('failure!'); }
);
This is a wrong way to do it. Ajax requests are asynchronous and not performed one after another as you expect them too. There is no way around that. You will have to redesign your code to nest ajax calls.
Something similar to this:
$.post("a.php", {function(data){
//1st check
$.post("b.php", {function(data){
//2nd check
$.post("c.php", {function(data){
//final actions
});
});
});
Only this way ajax calls will be stacked - the next will be performed after the previous.
Related
I have been trying to wrap my head around AJAX requests, and currently implementing some server-side validation for a twitter-bootstrap wizard in Javascript. I am experiencing some bizarre behavior where the function fails the first time its executed, but works as intended the second time. I have simplified my code into this structure:
function do_ajax_validate($user,$email) {
$.ajax({url: "checkuser.php?field=username&query=" + $user, success: function(result){
if (result != 'Valid')
{
$("#userlabel").html(result);
$("#userdiv").addClass("has-error");
$("#userdiv").removeClass("has-success");
$("#username").focus();
is_good[0] = false;
} else {
$("#userlabel").html($user + " is available!");
$("#userdiv").removeClass("has-error");
$("#userdiv").addClass("has-success");
is_good[0] = true;
console.log(is_good[0]);
}
}});
console.log(is_good[0]);
$.ajax({url: "checkuser.php?field=email&query=" + $email, success: function(result){
if (result != 'Valid')
{
$("#emaillabel").html(result);
$("#emaildiv").addClass("has-error");
$("#emaildiv").removeClass("has-success")
$("#email").focus()
is_good[1] = false;
} else {
$("#emaillabel").html('Looks good!');
$("#emaildiv").removeClass("has-error");
$("#emaildiv").addClass("has-success")
is_good[1] = true;
}
}});
console.log(is_good[0]);
console.log(is_good[1]);
if ((is_good[0])&&(is_good[1])) {
return true;
} else {
return false;
}
}
Whenever I go into the console and try to run the function, I call it with a user/email that I know is available and get this output:
do_ajax_validate('available_username', 'available#email.address');
false
false
false
Whenever I run the exact same line, I get this output:
do_ajax_validate('available_username', 'available#email.address');
true
true
true
Then checking on a username/email that I know is taken, it returns the last values:
do_ajax_validate('taken_username', 'taken#email.address');
true
true
true
And (you guessed it) - executing the function again returns the expected results:
do_ajax_validate('available_username', 'available#email.address');
false
false
false
I've been trying different methods for hours now and getting these same bizarre results. What am I doing wrong?
Ajax calls run asynchronously in javascript. Your success callback will only be executed once the Ajax call returns, thus your console.log()s can be called before the success functions executes.
You can have a two solutions for this problem:
Work with result inside the callback you assign to success property. Try to console result under the success property
use async: false under AJAX call like:
$.ajax({
url: "checkuser.php?field=username&query=" + $user,
async: false,
success: function(result){
console.log("result")
} });
I got a question concerning asynchronous calls. What I try to do is validate if a given "code" is valid. Refreshing the page is not an option.
The case in a nutshell:
I need to set a variable to true or false based on the reply from the server.
That call is done by using ajax.
The ajax ($.post) request processes the reply from the server and thus sets the variable to true or false.
The value of the variable will then be used as the return value for that function, true or false.The problem is to only return AFTER the ajax has completed. The asynchronous behavior of ajax prevents this and hanging the browser is not done.
The validation is done by using a function (it will en up being used in an if).
The if looks the following:
if(codeGiven()) {
// Code ok. Continue to process
} else { msgCodeInvalid(); }
The function codeGiven is the following
function codeGiven(toChk) {
var codeOK = false; // default answer
if(toChk) { // only perform call if toChk is not "" of undefined
$.post(
"validate.aspx", // server script
{ code: toChk }, // value
function(data) { // function
if(data == "true") {
codeOK = true; // when true => return will be true
} else {
codeOK = false; // when false => return will be false
}
}
);
}
return codeOK; // will be false by default but true when the code is OK
}
the aspx will use the posted "code" and match it against other codes in my database. If a match is found, the reply will be "true". If not, the reply will be "false".
Because an ajax call ($.post) is asynchronous, the result will always be false.
Any suggestions on how to hack my way out of this, besides my idea with a setInterval (a dirty method I know)? A return inside the post didn't work.
Any ideas?
Thanks in advance
Final solution
I came to the realization that I could put my entire logic inside the $.post.
so basically, my logic is the following (warning, it's a deep tree structure):
if(myvar) { // if pid not empty
$.post( // start validation
"validator.aspx", // server side validation script
{ code : myvar }, // data to be passed to the server
function(data, status) { // execute when post happend
if(data == "true") { // if answer from server == "true"
/*
assign variables
apply other logic
process effects
...
*/
} else { /* if answer from server == "false" => error: invalid code given */ }
}
).error( /* error: validator did a boom boom. We're sorry :( */ );
} else { /* error: please enter a code */ }
Do your check in the callback or promise of your function, for example:
function checkCodeGiven(toChk) {
return $.post("validate.aspx", { code: toChk });
}
And then something like:
checkCodeGiven(someVar).then(function(data) {
if(data == "true") {
// do whatever you wanted to do for true
} else {
// do whatever you wanted to do for false
}
});
you can :
. call the function you want inside the success function of the ajax
OR
. the delayer way :calling the part where you need the if(codeGiven) many times with delays about 100ms so you are sure that it's false or it becomes true at one call, replace this part
if(codeGiven()) {
// Code ok. Continue to process
} else { msgCodeInvalid(); }
with codeGiven();Delayer(0); and declair this
function Delayer(counter) {
if (codeOK) {
// Code ok. Continue to process
} else if (counter <10) { //not sure if it may become true later
setTimeout(Delayer, 100, counter++);} //call after 0.1 sec
else {
msgCodeInvalid(); // no hope to be true
}
}
plus codeOK should be declaired globally
hope this works for you
EDIT just clarified a bit
My experience in jQuery is limited and I've searched around for an answer but can't seem to find it.
This function returns a false or true based on a get. Now my problem is that the function 'Availability' doesn't return a false nor true if I get my data.
This is the code.
function Availability(){
var email = jQuery('#emailRegister').val();
jQuery.get("test.php", {email: email})
.done(function(data) {
if(data == 'true'){
jQuery(".warningEmailDuplicate").hide();
return true;
}else if(data == 'false'){
jQuery(".warningEmailDuplicate").show();
return false;
}
});
}
jQuery.get creates an AJAX request. These are asynchronous. You cannot return a value from the AJAX callback to the calling function. The function will have exited, returning nothing, before the HTTP request completes.
You need to rewrite your code to use callbacks:
function Availability(){
var email = jQuery('#emailRegister').val();
jQuery.get("test.php", {email: email})
.done(function(data) {
if(data == 'true'){
jQuery(".warningEmailDuplicate").hide();
AvailabilityResult(true);
}else if(data == 'false'){
jQuery(".warningEmailDuplicate").show();
AvailabilityResult(false);
}
});
}
function AvailabilityResult(available) {
// *available* will be true or false
// do with this value what you wanted to do with the return value from Availability
}
JQuery is Async scripting language, so when you calls this method compiler does not wait to get the return value.
When you call Availablity(); then off-course an Ajax get request sends to test.php and in the mean time compiler returns nothing from your method and assign variable seems undefined.
To prevent this issue, you need to create a callback function rather than simple return the value.
see example with no callback and example with callback
Try this code:
function Availability(callback){
var email = jQuery('#emailRegister').val();
jQuery.get("test.php", {email: email})
.done(function(data) {
if(data == 'true'){
jQuery(".warningEmailDuplicate").hide();
callback(true);
}else if(data == 'false'){
jQuery(".warningEmailDuplicate").show();
callback(false);
}
});
}
//calling function
Availablity(function(status){
var available = status;
alert(available);
});
jQuery(document).ready(function(jQuery) {
function checkEmail(email){
jQuery.post('someroute.php',
{email:eamil},
function(data){
if(data==error){
return false;
}
);
return true;
}
jQuery('#myform').submit(function(){
// como code and at the momment this
var result true;
//then I check email
var email = ('#myemail').val();
result = checkEmail(email);
return result;
});
The problem is this, a checkEmail function, first return true, and then return value jQuery.post function. Why?
I checked and in submit, first return true, and if you stop submit then you release that post return the value. Post works fine, but I don't understand why function checkEmail does not wait until post returns the value and goes on until the end to return true.
Because the jQuery.post() function is an AJAX request, and the first A in AJAX stands for asynchronous. That's exactly what asynchronous is, it doesn't stop code execution while it waits for a response. It fires the request and then immediately moves on to any code after the line making the request, in this case your return true statement.
Like Anthony Grist said. .post is an asynchronous call which means it doesn't wait to finish.
I've looked up the .post method (http://api.jquery.com/jQuery.post/).
It's basicly a shortcut for .ajax. You're missing the fail method in here so I would say use the .ajax call.
var value = 1;
var handlerUrl = "someroute.php";
//Do the Ajax Call
jQuery.ajax(
{
url: handlerUrl,
data: { email:eamil },
type: 'POST',
success: function (data)
{
return true;
},
error: function (jxhr, msg, err)
{
return false;
}
});
#user1727336 : Hi! You might want to edit your code and add the missing } and });. Here's a fix:
// enter code here
jQuery(document).ready(function(jQuery) {
function checkEmail(email){
jQuery.post('someroute.php', {email:eamil},
function(data){
if(data==error){
return false;
}
});
return true;
}
});
I have a registration form. When I hit the Submit button it should check if the Username is not taken and that the passwords match. So I wrote a few functions: one that checks the passwords, one that checks if the username is available and the main function, that calls for the 2 checking functions. The password checking function works nice, but my problem is with the username checking function. This is the function:
function checkIsUsernameExist(){
if($("#txtNewUsername").val() == "") {
$("#divIsUsernameExist").html("");
return false;
} else {
$.getJSON("inc/API.php",
{
command : 'isUsernameExist',
username : $("#txtNewUsername").val(),
},
function(result)
{
if (result != true){
$("#divIsUsernameExist").html("This username is available!");
return true;
} else {
$("#divIsUsernameExist").html("This username is not available!");
return false;
}
});
}
}
When the username is empty, it does return False. But when some value is entered it returns Undefined.
Somebody told I should use Synchronous JAX (but didn't tell me how), so I tried to write this code:
function checkIsUsernameExistAsync(){
if($("#txtNewUsername").val() == "") {
$("#divIsUsernameExist").html("");
return false;
} else {
$.ajax({
type: 'POST',
url: 'inc/API.php',
data: ({
command : 'isUsernameExist',
username : $("#txtNewUsername").val(),
cache: false,
async: false
}),
success: function(result){
if (result != true){
$("#divIsUsernameExist").html("This username is available!");
return true;
} else {
$("#divIsUsernameExist").html("This username is not available!");
return false;
}
}
});
}
}
But I get the same result - False when it's empty, Undefined when some value is entered. I tried to change $.ajaxto $.getJSON in the second function, but still had the same result.
This is the code from API.php:
case "isUsernameExist":
echo (isUsernameExist($_REQUEST["username"]));
break;
it calls for a function in included page BusinessLogic.php, here's this function:
function isUsernameExist($username)
{
$arr = select("select * from users where username='$username'");
if(count($arr) == 1)
return json_encode(true);
else
return json_encode(false);
}
How can I make it work??
Thank you!
To summarise the comment chain:
Avoid synchronous AJAX requests: Remove async: false
Add `dataType: 'json',
return inside a success handler of jQuery.ajax does not set the return value of the outer function. To correctly pass the results, define a callback handler. Replace:
Before: http://jsfiddle.net/wGfzc/
After: http://jsfiddle.net/wGfzc/2/