I currently have this function:
function devuelveButaca(posicion){
var array = posicion.split('_');
var row = array[0];
var column = array[1];
var planta = $('#plantaField').val();
var resultado = "";
$.ajax({
type : 'GET',
url : 'site/numButaca',
data : {
planta : planta,
column : column,
row : row
},
success : function(data) {
if(data == 'undefined' || data == ''){
resultado = column;
}else{
resultado = data;
}
},
error : function(request, status, error) {
},
});
alert(resultado);
return resultado;
}
Which returns the result correctly, the problem is that unless it goes into debug mode, or puts an alert before the return, resultado
it returns empty. Currently, the alert exits empty but correctly returns the result (I use it to add the variable text to a div).
I have read that it can be solved by setting a Timeout, but I would like to know if there is a more elegant solution than this.
Explanation of the problem.
The A in Ajax stands for Asynchronous; this means that the request is outside the normal flow of execution. In your code, the
$.ajax
, when executed, follows the return,return resultado
, and this is executed before the function or ajax request passes the value of the response to success. Therefore when you use the alert it returns empty or undefined, since the request you made has not returned.Possible solutions that you can give to your problem:
ES2017+: Promises with async/await
The version of ECMAScript released in 2017 introduced support for asynchronous functions. With the help of async and await , you can write asynchronous code in a synchronous style. The code will still be asynchronous but it is easier to read and understand.
Async/await is based on promises, an async function will always return a promise. the Await takes the information from the promise and the result will be the value that was resolved, or else the error if it has been rejected.
Here is an example of how to create async at a high function level:
Using Async in functions:
Current browser and node versions support async/await. You can also support older environments by transforming your code to ES5 with the help of regenerator (or tools that use regenerator, such as Babel).
Current versions of browsers and node support async / await. It is also supported by previous versions making use of ES5 under tools such as Babel.
Using callback functions: A callback is a function that will be called later when the Ajax request has finished.
Example:
This example demonstrates that the property
success
should receive a function, which jQuery will call at the end of the request if it was successful. By the way, there is another callback available to control what to do in case of errors. It is handled using the propertyerror
; receives a callback that will be invoked in case of no success.Use the promises:
Promises are containers for future values. When a promise receives the value if it was resolved or canceled, it will notify listeners that it wants to access that return value. One of the added values is that it has more code reading and in my opinion it is a much better approach. Example:
Use Jquery Deferred
This is a custom implementation of promises implemented by jQuery; usage is very similar to the point explained above:
Source - How do I return the response from an asynchronous call?
one of the solutions you could do is to remove the Async so that you have an immediate response by placing(async: false).
When making an Ajax call, it is executed asynchronously, that is, while the request is made, the execution of the function you have there continues.
For that you have success and error callbacks.
If you put an alert inside the Success you will be able to see the result.
One solution would be to pass your function a callback to execute it.
And you call it like this:
The value of
resultado
returns empty because it's got through an asynchronous (AJAX) call but you're returning it synchronously (so the value hasn't been instantiated yet).As you say, a possible solution would be to add a wait (or a
timeout
) to make sure that the value is going to be obtained. But that can have problems: what if the value of the wait is not enough? Then you would still have the same problem and the value would return null.Actually this is an incorrect use of AJAX. The idea is not that you return something (which would be synchronous) but that you use the values when you receive them asynchronously (in the
success
).For that you could do two things:
Move the code from where you call the function to the
success
. Although this option may not be very good if it is called for different reasons or from different functions todevuelveButaca()
.Pass as a parameter a callback function that will be called from the
success
. That way, you could calldevuelveButaca()
from different contexts and it would always work.