Ajax response with Javascript returns Undefined - javascript

I am trying to pass a variable from a form field to a function which in returns checks if the value exists from the database and returns either exists or not_exist, but this it returns undefined.
registerButtonAction.addEventListener('click', function() {
disableRegisterButton();
var getRegisterUsername = document.getElementById('registerUsername').value;
var confirmUser = validatedUser(getRegisterUsername);
alert(confirmUser); //alerts undefined instead of exist, or not_exist
if (confirmUser === 'not_exist') {
alert('Okay');
}
});
function checkRegisterUsername(getRegisterUsername){
$.ajax({
type:"post",
url: "accounts/users/checkUsername/"+getRegisterUsername,
data:{getRegisterUsername:getRegisterUsername},
success: function(data){
if(data==='exists'){
var a='exists';
return a;
}else if(data==='not_exist'){
var a='not_exist';
return a;
}else if(data==='navigation_error'){
enableRegisterButton();
document.getElementById('resistrationStatus').innerHTML="<small style='font-size: 15px; color: #ac2925'><i class='fa fa-info-circle'></i> FATAL ERROR OCCURRED, RELOAD PAGE</small>";
}else{
enableRegisterButton();
document.getElementById('resistrationStatus').innerHTML="<small style='font-size: 15px; color: #ac2925'><i class='fa fa-info-circle'></i> FATAL ERROR OCCURRED, RELOAD PAGE</small>";
}
},
error: function() {
alert("Error Occured, Check your connection and try again.");
}
});
}

I guess your validateUser(..) function will call your ajax. In your case i think your ajax call isn't finish yet when alert is fired.
Try to move this part at the end of ajax's success. Or you can either add async: false as paremeter of ajax. With async to false it will wait for the end of the call before move on.

I suppose that validatedUser and checkRegisterUsername are the same function, and you forgot to change the names.
AJAX calls are tipically asynchronous. This means that you can't wait for a return value: success function will be executed when the AJAX call will succeed, but in a separate context.
Even if you make the AJAX call synchronous, return in a success/error callback is meaningless. Also, the return value you are trying to catch is the one of checkRegisterUsername, that does not have a return status at all, that's why is undefined.
To achieve what you want, try to put the alert part inside the success handler, i.e. instead of return a write alert(a) and see what happens.

Related

How can I make a jquery $.when statement refire if it fails?

So sometimes due to some kind of server asynchronicity issue, or something.. I don't know what, but it only happens every once in a while (s_mcir_2 calls its own AJAX functions that are cross-domain, so the other server I suppose can be unreliable).. Anyway, every once in a while result is returned from s_mcir_2 as null instead of a JSON object.
When this happens, I would like to test if it is null, and then if it is, have the $.when statement refire.. theoretically until it receives valid output.
Any ideas?
$.when(s_mcir_2(alt, data[l_alt])).then(function(result) {
//EVALUATE "result"
});
Deferred objects can only resolve once.
Try using a named function that calls itself on fail.
function myFn () {
$.when(s_mcir_2(alt, data[l_alt])).then(function(result) {
//EVALUATE "result"
if (!result) {
setTimeout(myFn,125);
log("R_MCIR_2 has failed");
}
else {
// success, do stuff
...
}
});
}
.then() can take two callback functions, one for done and one for fail. If you run your code inside a function you can recursively re-run your AJAX request (note that this could create an infinite loop):
var failedCount = 0;
function some_func() {
$.when(s_mcir_2(alt, data[l_alt])).then(
//done callback
function(result) {
//EVALUATE "result"
},
//fail callback
function () {
failedCount++;
if (failedCount < 10) {
//try again
some_func();
}
});
}
Docs for .then(): http://api.jquery.com/deferred.then
This code assumes that the s_mcir_2() function returns a jqXJR object (e.g. return $.ajax(...)).
Notice I added a counter to the failed function so this process won't continue infinitely. Once 10 requests have been made, the recursiveness stops.
UPDATE
If instead of the jqXHR object being rejected, if it is resolving to success you can check the server response and if it is null (e.g. typeof(serverResponse) == 'null') then re-run the some_func() function.
function attempt(){
$.when(s_mcir_2(alt, data[l_alt])).then(function(result) {
//EVALUATE "result"
}).fail(function(result) {
log("R_MCIR_2 has failed");
setTimeout(attempt,500)
});
}

check that a task is completed

I have a javascript function which supposed to check whether a task is completed.
When the task is completed there is a completion record in a file on the server.
The function supposed to make recursive calls to the server with some delay (potentially increasing) till it gets the completion record in the file.
The code given below makes excessive calls to the server with interval less than a second
example from Web Console:
[20:06:21.202] [20:06:21.563] [20:06:21.990]
But the task becomes competed on variable waittime value getting equal to max_waittime .
Though for a test case overall output is as expected, something is wrong with the function.
Where I'm wrong?
function check_status(time,div_id,filename) {
var status =0;
var waittime=time;
var max_waittime=11000000;
if (waittime < max_waittime){waittime=waittime+1000000; }
$.ajax({
type: "GET",
async: false,
url: "code_on_server_checking_file.php",
data: "f="+filename,
dataType: "text",
success: function(content) {
if (content ) {
// stuff related to output of the result
....
return status=1;
}
else {return status=0;}
}
});
if (status == 0 && waittime < 20000000){
setTimeout(check_status(waittime,div_id,filename),waittime);
}
else {alert('check_status passed!'+status+'|'+waittime);}
}
You need to pass check_status to setTimeout, not the value returned by invoking check_status(...). Since you need to pass parameters to check_status, use an anonymous function:
setTimeout(function () {
check_status(waittime, div_id, filename);
}, waittime);
You are calling the function instead of giving it as a reference to setTimeout. Wrap your function call in an anonymous function. Also, it would be better to simply set up the call in the ajax callback if needed rather than using a synchronous call. A synchronous call will tie up your browser.
function check_status(time,div_id,filename) {
$.ajax({
type: "GET",
url: "code_on_server_checking_file.php",
data: "f="+filename,
dataType: "text",
success: function(content) {
if (content ) {
// stuff related to output of the result
}
else {
time += 1000000;
if (time < 20000000) {
setTimeout( function() { check_status( time, div_id, filename); }, time );
}
}
}
});
}
"recursive calls to the server"? No, I don't think you want that.
If you go three deep, var max_waittime=11000000; will be created and initialized three times.
Maybe you can set the timeout value for the ajax call (ajax settings)
http://api.jquery.com/jQuery.ajax/
First of all, it looks like you don't understand that the ajax call is an asychronous call. Calling it just starts the networking operation and then the rest of your code continues executing. Some time later when the networking operation completes, your success function is called.
The ONLY place you can operate on the results of the ajax call is in the success function. You can't return a value from the success function and expect that to go anywhere. The only place that goes is somewhere inside the ajax code where it's dropped. If you need to do something with the results of the ajax call, then you need to either do that operation right in the success function or call some other function from the success function and pass it the returned data.
These are the parts of your code that do not work:
There's no point in returning the status value from the success function. It doesn't go anywhere except into the ajax function where the return value is just dropped.
This line of code if (status == 0 && waittime < 20000000){ is not doing what you want. Because the ajax call is asynchronous, the value of status has not yet been set by the ajax call when this line of code runs. Thus, it's ALWAYS 0 so your logic never works. You need to move this logic inside the success handler.
As others have said, your parameters to setTimeout are not right. You have to pass a function to setTimeout, not the results of executing a function.
This is the code I would suggest:
function check_status(time, div_id, filename) {
var max_waittime=11000000;
if (time < max_waittime){
time=time+1000000;
}
$.ajax({
type: "GET",
async: false,
url: "code_on_server_checking_file.php",
data: "f="+filename,
dataType: "text",
success: function(content) {
if (content ) {
// stuff related to output of the result
if (time < 20000000){
setTimeout(function() {check_status(time, div_id, filename)}, time);
}
}
}
});
}
Note that all handling of the ajax result is done in the success function and we pass an anonymous function to setTimeout that re-calls check_status after a time delay. This is not actually recursion (as others mentioned) because setTimeout allows check_status to return before it's called again some time later.

jquery - return value from callback function (in post request) into the function its inside of?

I have a javascript function that posts data to a validation script and grabs a value from there. The callback function on the post request returns a boolean value, and I'm trying to get the entire function to return that boolean value. Right now, the callback function returns the correct value, but the function itself doesn't return anything. Here's the code:
function validate(request_type, request_text) {
$.post("http://www.example.com/ajax/validate.php",{
type: request_type,
text: request_text
}, function(data) {
return (data == "valid");
});
}
I realise that this is sort of a "synchronous" call, and that's not what AJAX is about, but I already have numerous functions in validate.php (database calls, etc.) that I can't implement in Javascript, and I saw threads like this one that talk about using some form of handler.
How would I write a simple handler that will make either the variable data or the result of the boolean comparison data == "valid" available when I use it in an if/else statement (which is where this function is supposed to be used)?
EDIT: For example, one of the if statements that will be using the boolean result:
if (!validate('password',pass_new)) {
$('#pass_new').addClass('error');
$('#pass_confirm_new').addClass('error');
$(error_string.format('Please enter a valid password.')).insertAfter('#pass_confirm_new');
$('#pass_text_short').hide();
$('#pass_text_long').show();
EDIT: The function called with the onsubmit event in my HTML form:
function valid_pass_sett() {
//code to remove errors left over from previous submissions - snipped
pass_old = $('input[name=pass_old]').val();
pass_new = $('input[name=pass_new]').val();
pass_confirm_new = $('input[name=pass_confirm_new]').val();
//some if statements that don't involve AJAX requests - snipped
if (!validate('password',pass_new)) {
$('#pass_new').addClass('error');
$('#pass_confirm_new').addClass('error');
$(error_string.format('Please enter a valid password.')).insertAfter('#pass_confirm_new');
$('#pass_text_short').hide();
$('#pass_text_long').show();
return false;
}
return true;
}
I haven't edited this code to include the updated code that's been posted, but my question is how I return false from it to stop form submission?
function validate(request_type, request_text, callback) {
$.post("http://www.example.com/ajax/validate.php",{
type: request_type,
text: request_text
}, function(data) {
callback(data == "valid");
});
}
And usage would be:
validate(request_type, request_text, function (isValid) {
if(isValid) {
// do something
} else {
// do something if invalid
}
});
Unless you make a synchronous AJAX call (which you probably don't want to do), you simply can't.
If this function is used in several places in your code, your best bet may be to allow it to receive a function.
That way instead of relying on the result being returned from your function to be used in some code, you're actually passing your code directly in, so it is ensured to be able to use the response.
var my_form = $('#my_form');
my_form.submit( valid_pass_sett );
function valid_pass_sett() {
//code to remove errors left over from previous submissions - snipped
pass_old = $('input[name=pass_old]').val();
pass_new = $('input[name=pass_new]').val();
pass_confirm_new = $('input[name=pass_confirm_new]').val();
validate('password', pass_new, pswd_validation_callback); // async validation
return false; // cancel form submission
}
function validate(request_type, request_text, callback ) {
$.post("http://www.example.com/ajax/validate.php",{
type: request_type,
text: request_text
}, callback );
}
function pswd_validation_callback( data ) {
if ( data === 'valid' ) {
// if valid, call the native .submit() instead of the jQuery one
my_form[ 0 ].submit();
} else {
// Otherwise do your thing for invalid passwords.
// The form has already been canceled, so no concerns there.
$('#pass_new').addClass('error');
$('#pass_confirm_new').addClass('error');
$(error_string.format('Please enter a valid password.')).insertAfter('#pass_confirm_new');
$('#pass_text_short').hide();
$('#pass_text_long').show();
}
}
EDIT: Changed to use code posted in question.
EDIT: Updating to work with additional code posted. Narrowing answer down to the named function for clarity.
function validate(request_type, request_text) {
$.post("http://www.example.com/ajax/validate.php",{
type: request_type,
text: request_text
}, function(data) {
return (data == "valid");
}); }
You can't really return from 'validate' the result of the AJAX call. You could try declare a variable before the $.post call, let's call it 'x', and inside the response function assign the value to that variable (x=data=="valid"), and outside the $.post block, but inside the 'validate' function, return that value.
function validate(request_type, request_text) {
var x;
$.post("http://www.example.com/ajax/validate.php",{
type: request_type,
text: request_text
}, function(data) {
x = data == "valid";
});
return x; }
The real problem is that the function 'validate' will continue even if the post call haven't return any value, so it will always be 'false'.
The best thing you can do is call another function INSIDE the response function, so you can assure that the server call is over before getting to the next part.
Edit:
It's been a long time since I posted this answer. The world has changed and so AJAX calls.
Now we have promises ;)
You still cannot return a direct value from a function, but you can return a Promise object, which can be chanined to another Promise, and the second promise will get the data you returned from the first one.
function validate(request_type, request_text) {
var promise = $.ajax("http://www.example.com/ajax/validate.php",{
type: request_type,
text: request_text
});
function getStuff(data) {
//Do something and return the data to the next promise
return data;
}
promise.then(getStuff).then(function(data){
// Do something else with data
});
}
If I understand this question correctly you can achieve what you want by simply storing the returned value into a HTML element and then return that elements value from your custom function:
function validate(request_type, request_text){
$.post("http://www.example.com/ajax/validate.php",{
type: request_type,
text: request_text},
function(data) {
$('#someElement').text(data);
});
//return the data by getting the value of the html element
return $('#someElement').text();
}

Need help with Extjs function returning undefined results

I want to do the following with my javascript codeblock.
Handle all current and new device requests ie. detect,encrypt,decrypt,etc
Return the result to the calling method
Questions
How can I improve the existing code and get rid of the javascript strict warning:anonymous function does not always return a value.
What is the right way of calling my method?
Any help is greatly appreciated
Thanks!
Herewith the code:
This is how I call the current method
//Contents of SmEditor.js
var response = Ext.decode(Prometheus.DeviceRequestHelper.detect(request_id));
//contents of Sm.js
Ext.ns('myApp')
myApp.DeviceRequestHelper = {
detect:function(request_id){
var task = function(){
Ext.Ajax.request({
url: 'device_requests.php',
params:{
action:'get_device', //in php
'request_id':request_id
},
timeout:30000, //30 seconds
success:function(response){//serverside response
var result = Ext.decode(response.responseText); //convert to js objects
if(result.success == true){//device was detected
cons.log('success,device was detected');
cons.log(result);
Ext.TaskMgr.stop(runTask);
return Ext.encode(result); //javascript strict warning
}else{
if(runTask.taskRunCount >= 10){
//retry limit exceeded
Ext.Msg.show({
title:'Server Failure',
msg:"Detection Failed,Unable to detect device",
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
Ext.MessageBox.getDialog().getEl().setStyle('z-index','80000');
Ext.TaskMgr.stop(runTask);
}
}
},
failure:function(response){
Ext.TaskMgr.stop(runTask);
Ext.Msg.show({
title:'Server Failure',
msg:"Failed, server communication error",
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
Ext.MessageBox.getDialog().getEl().setStyle('z-index','80000');
}
})
}
var runTask = {
run: task,
interval:2000,
repeat:10
};
Ext.TaskMgr.start(runTask);
}
}
To prevent this kind of warning, have the function return a value in all cases, or no cases. At the moment you're only returning a value in one if case; the other cases will not return anything. You can even return undefined to make the warning go away. However, what it is telling you is correct: that a function that sometimes has a return value and sometimes doesn't is a bit weird and suggests you're doing something wrong.
What you seem to want to do is have the inner return in the success method return a value from the detect() method. This is absolutely not possible. The inner function can only return a value to the caller of success, which is Prototype itself. By the time this happens, the detect() method has long since returned.
What you have here is asynchronous code. The detect() method can set up an AJAX request, but it must then return immediate to its caller, which will return control to the browser. At some later time, the HTTP request behind the AJAX call will complete, and then the success function will fire. JavaScript cannot call asynchronous code synchronously, or vice versa.
What you have to do is pass a callback function into your method, and then call it back on completion:
Prometheus.DeviceRequestHelper.detect(request_id, function(response) {
// do something with `response`
});
myApp.DeviceRequestHelper= {
detect: function(request_id, callback) {
...
Ext.Ajax.request({
...
success: function(xhr) {
var result= Ext.decode(xhr.responseText);
if (result.success)
callback(result);
...
},
...
});
},
...
};
(I removed the extra Ext.encode->Ext.decode pair, that just seems like a waste of time.)
First, Your detect method will not return a value and will return immediately(even before the ajax call completes) because the ajax call is asynchronous
Second, there's no point returning a value in your success handler. Instead you should provide a callback function to your detect method like so:
Ext.decode(Prometheus.DeviceRequestHelper.detect(request_id, function(response) {
// do something with your response
}));
// detect function takes a callback function as a parameter
myApp.DeviceRequestHelper = {
detect:function(request_id, funCallback){ // pass in a callback function that is
// called when result was a success
var task = function(){
Ext.Ajax.request({
url: 'device_requests.php',
params:{
action:'get_device', //in php
'request_id':request_id
},
timeout:30000, //30 seconds
success:function(response){//serverside response
var result = Ext.decode(response.responseText); //convert to js objects
if(result.success == true){//device was detected
cons.log('success,device was detected');
cons.log(result);
Ext.TaskMgr.stop(runTask);
// return Ext.encode(result); //javascript strict warning
funCallback(Ext.encode(result)); // ===========> callback function called.
}else{
if(runTask.taskRunCount >= 10){
//retry limit exceeded
Ext.Msg.show({
title:'Server Failure',
msg:"Detection Failed,Unable to detect device",
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
Ext.MessageBox.getDialog().getEl().setStyle('z-index','80000');
Ext.TaskMgr.stop(runTask);
}
}
},
failure:function(response){
// ... failure handing code
}
});
}
var runTask = {
run: task,
interval:2000,
repeat:10
};
Ext.TaskMgr.start(runTask);
}
}

Jquery $.post() variable scope

I'm not massively experienced with JavaScript and I'm having trouble with variable scope and jquery. I have the following structure:
function pass_variables()
{
username = "efcjoe"
response = post_variables(username)
alert(response)
}
function post_variables(username)
{
$.post(
'/path/to/url/',
{
'username': username,
},
function(data)
{
valid = (data != 0) ? true : false
// OPTION 1: If I put return here...
return valid; // ... the alert box in pass_variables says "undefined"
},
"text"
);
// OPTION 2: If I put return here...
return valid; // ... The alert box does not pop up, and Safari debug gives
// me the error: "Can't find variable: valid"
}
Am I missing something there? I think valid should be a global variable, and therefore option 2 should work fine. I'm really not sure about option 1.
Can anyone give me any advice on the best way to get this working?
Thanks a lot.
Ajax calls are asynchronous which means they get called but do wait around for execution to complete. Basically your alert is firing before the ajax request has completed and run the callback function to change your variable.
The best thing you can do is actually pass a function to run when the ajax request has completed. This also negates the need for global variables which are frowned upon since other plugins, script can alter their state and leave your script open to errors, flaws etc
E.g
function foobar(){
//call function to do post request and also pass a function to run
//when post has returned
runPostRequest( callbackFn );
}
function runPostRequest(callback){
$.post( '/foo', callback );
}
function callbackFn( data ){
console.log('post request complete');
}
In your option 1 you are returning from the callback function, and its return value is never used because this function is only called when the Ajax request ends.
In the option 2, you are returning from your main function, but that return happens before the callback function assign any value to your valid variable.
I would refactor your code in this way, without using global variables:
function post_variables(username){
$.post('/path/to/url/',{
'username': username,
},
function(data){
var valid = data != 0;
// OPTION 3: Work in the callback function
alert(username);
alert(valid);
// OPTION 4: Pass the values and work on another function
otherFunction(username, valid);
},"text");
}
function otherFunction(username, isValid){
//...
}
Yeah, your problem is that you're not grasping some order of operations issues here. The function you're passing to $.post is a callback; it runs later, considerably after post_variables() finishes. post_variables() itself does not wait for the $.post to finish, so valid doesn't exist when you're trying to use it.
Remember that AJAX is asynchronous. The return valid; gets executed immediately after the $.post() is set up, but before the post has completed (and therefore, before valid is defined). What you probably want to do is this:
function post_variables(username)
{
var username = "efcjoe";
$.post(
'/path/to/url/',
{
'username': username,
},
function(data)
{
var valid = (data != 0) ? true : false
alert(valid);
},
"text"
);
}
And note that this no longer needs global variables, but function-scope variables that are declared using var.
You could solve the problem quite easily by assigning it a function instead of an inline one, and the event function does the alert:
function pass_variables()
{
username = "efcjoe"
response = post_variables(username);
}
function post_variables(username)
{
$.post(
'/path/to/url/',
{
'username': username,
},
receivedData,
"text"
);
}
function receivedData(data)
{
valid = (data != 0) ? true : false;
alert(valid)
}

Categories