I have a function foo
which makes an Ajax request. How can I return the response from foo
?
I tried returning the value from the success
callback, as well as assigning the response to a local variable inside the function and returning that one, but none of those ways actually return the response.
function foo() {
var result;
$.ajax({
url: '...',
success: function(response) {
result = response;
// return response; // <- I tried that one as well
}
});
return result;
}
var result = foo(); // It always ends up being `undefined`.
Angular1
For people who are using AngularJS, can handle this situation using
Promises
.Here it says,
You can find a nice explanation here also.
Example found in docs mentioned below.
Angular2 and Later
In
Angular2
with look at the following example, but its recommended to useObservables
withAngular2
.}
You can consume that in this way,
See the original post here. But Typescript does not support native es6 Promises, if you want to use it, you might need plugin for that.
Additionally here is the promises spec define here.
Short answer is, you have to implement a callback like this:
Using ES2017 you should have this as the function declaration
And executing it like this.
Or the Promise syntax
XMLHttpRequest 2 (first of all read the answers from Benjamin Gruenbaum & Felix Kling)
If you don't use jQuery and want a nice short XMLHttpRequest 2 which works on the modern browsers and also on the mobile browsers I suggest to use it this way:
As you can see:
There are two ways to get the response of this Ajax call (three using the XMLHttpRequest var name):
The simplest:
Or if for some reason you
bind()
the callback to a class:Example:
Or (the above one is better anonymous functions are always a problem):
Nothing easier.
Now some people will probably say that it's better to use onreadystatechange or the even the XMLHttpRequest variable name. That's wrong.
Check out XMLHttpRequest advanced features
It supported all *modern browsers. And I can confirm as I'm using this approach since XMLHttpRequest 2 exists. I never had any type of problem on all browsers I use.
onreadystatechange is only useful if you want to get the headers on state 2.
Using the
XMLHttpRequest
variable name is another big error as you need to execute the callback inside the onload/oreadystatechange closures else you lost it.Now if you want something more complex using post and FormData you can easily extend this function:
Again ... it's a very short function, but it does get & post.
Examples of usage:
Or pass a full form element (
document.getElementsByTagName('form')[0]
):Or set some custom values:
As you can see I didn't implement sync... it's a bad thing.
Having said that ... why don't do it the easy way?
As mentioned in the comment the use of error && synchronous does completely break the point of the answer. Which is a nice short way to use Ajax in the proper way?
Error handler
In the above script, you have an error handler which is statically defined so it does not compromise the function. The error handler can be used for other functions too.
But to really get out an error the only way is to write a wrong URL in which case every browser throws an error.
Error handlers are maybe useful if you set custom headers, set the responseType to blob array buffer or whatever...
Even if you pass 'POSTAPAPAP' as the method it won't throw an error.
Even if you pass 'fdggdgilfdghfldj' as formdata it won't throw an error.
In the first case the error is inside the
displayAjax()
underthis.statusText
asMethod not Allowed
.In the second case, it simply works. You have to check at the server side if you passed the right post data.
cross-domain not allowed throws error automatically.
In the error response, there are no error codes.
There is only the
this.type
which is set to error.Why add an error handler if you totally have no control over errors? Most of the errors are returned inside this in the callback function
displayAjax()
.So: No need for error checks if you're able to copy and paste the URL properly. ;)
PS: As the first test I wrote x('x', displayAjax)..., and it totally got a response...??? So I checked the folder where the HTML is located, and there was a file called 'x.xml'. So even if you forget the extension of your file XMLHttpRequest 2 WILL FIND IT. I LOL'd
Read a file synchronous
Don't do that.
If you want to block the browser for a while load a nice big
.txt
file synchronous.Now you can do
There is no other way to do this in a non-asynchronous way. (Yeah, with setTimeout loop... but seriously?)
Another point is... if you work with APIs or just your own list's files or whatever you always use different functions for each request...
Only if you have a page where you load always the same XML/JSON or whatever you need only one function. In that case, modify a little the Ajax function and replace b with your special function.
The functions above are for basic use.
If you want to EXTEND the function...
Yes, you can.
I'm using a lot of APIs and one of the first functions I integrate into every HTML page is the first Ajax function in this answer, with GET only...
But you can do a lot of stuff with XMLHttpRequest 2:
I made a download manager (using ranges on both sides with resume, filereader, filesystem), various image resizers converters using canvas, populate web SQL databases with base64images and much more... But in these cases you should create a function only for that purpose... sometimes you need a blob, array buffers, you can set headers, override mimetype and there is a lot more...
But the question here is how to return an Ajax response... (I added an easy way.)
This is one of the places which two ways data binding or store concept that's used in many new JavaScript frameworks will work great for you...
So if you are using Angular, React or any other frameworks which do two ways data binding or store concept this issue is simply fixed for you, so in easy word, your result is
undefined
at the first stage, so you have gotresult = undefined
before you receive the data, then as soon as you get the result, it will be updated and get assigned to the new value which response of your Ajax call...But how you can do it in pure javascript or jQuery for example as you asked in this question?
You can use a callback, promise and recently observable to handle it for you, for example in promises we have some function like
success()
orthen()
which will be executed when your data is ready for you, same with callback or subscribe function on observable.For example in your case which you are using jQuery, you can do something like this:
For more information study about promises and observables which are newer ways to do this async stuffs.
Here are some approaches to work with asynchronous requests:
Example: jQuery deferred implementation to work with multiple requests