This is probably really stupid but i can't find the problem with my code. It fetches a url that returns json and the function is then supposed to return a string:
function getit() {
var ws_url = 'example.com/test.js';
var user = false;
$.getJSON(ws_url, function(data) {
alert('user '+data.user);//shows john
user = data.user || false;
});
return user;//should return john but returns false
}
test.js will have something like this:
{"id":"12","username":"ses","user":"john","error":""}
or like this:
{"error":"123"}
I also tried if (data.user) {} else {} but it didn't work either..
So what am i missing?
Thanks :)
The problem comes from the fact that the $.getJSON() call is asynchronous. Once the ajax request is fired off, processing continues on inside getit(), and your function immediately returns false. Later on, the Ajax response returns and sets user, but your getit() function returned a long time ago!
You can force the Ajax call to be synchronous using the async option, like this:
$.ajax({
async: false,
url: ws_url,
type: "GET",
success: function(data) {
alert('user '+data.user);//shows john
user = data.user || false;
}
});
If you do that, your browser will block on the script until the Ajax call returns. Generally this isn't the ideal behaviour (which is why the default is async: true), so I'd suggest reworking whatever it is that's calling getit(), and have it expect to process it's results whenever it can, perhaps by passing it's own callback function to getit() that would then be executed when getit() is done.
Ajax is asynchronous, which means that the rest of the script isn't going to sit around and wait for it to finish before moving on. As in your example, the return line is being reached before the ajax function receives a response from the server, thus the user variable is still false at that point in time.
If you want to force an ajax call to run synchronously, you can use jQuerys $.ajax method and set the async parameter to false.
$.ajax({
url:ws_url,
dataType:"json",
async:false,
success:function(data){
alert('user '+data.user);//shows john
user = data.user || false;
}
});
Related
I am trying to write a jquery plugin.
Now, I would like to use an ajax-call in one of the functions of this plugin.
However it should be chainable, meaning in this case that the ajax-call should be executed and only after something was returned, the return should happen.
I tried different things but so far I could not make it so that the second function in the chain is really executed after the return value of the ajax call was retrieved;
In this version (see below) I can use
$(document).createDatabase().message();
So, chaining works.
But looking at the console log – the message() function is executed before the ajax-call in createDatabase() is finished.
How can I make it so that
$(document).createDatabase().message();
first returns the output/return of the ajax-call that is inside createDatabase() and only after that message() is executed?
Code:
(function($) {
$.fn.createDatabase = function(options) {
// Plugin options defaults
var settings = $.extend({
name: 'NA',
onExit: function() {} // callback function
}, options);
$.ajax({
method: "POST",
url: "plugin/php/createDatabase.php",
data: settings
})
.done(function(msg) {
console.log("createDatabase executed with message: " + msg);
settings.onExit.call();
});
return this;
};
$.fn.message = function() {
console.log('this should appear after the console-log message of createDatabase');
return this;
}
}(jQuery));
Thank You!
You could do a couple of things, but they are all a bad idea. The reason is that these are two separate jQuery plugins - a plugin should be capable of working on its own. There is no guarantee or reason that somebody won't do .message().createDatabase(). If you need to guarantee the order of execution, then you should use just one plugin. One possible way would be to pass message inside options when you call .createDatabase(options), and then run message when the call is done. Like so
$(document).createDatabase({
message: function() {...}
});
...
var promise = $.ajax({
method: "POST",
url: "plugin/php/createDatabase.php",
data: settings
})
.done(function(msg) {
console.log("createDatabase executed with message: " + msg);
settings.onExit.call();
});
...
if ( settings.message )
promise.done( settings.message.bind(this) );
I tried different things but so far I could not make it so that the second function in the chain is really executed after the return value of the ajax call was retrieved;
The second function executes when the first one finishes. The first one finishes with return this, but this happens before the ajax call is done because ajax calls are asynchronous.
On alert it always alerts jojo. The test2.php have text Loco
The div gets updated to Loco but the global variable is not changing. I tried window.temp = data but it didn't worked.
How can i get the returned value in variable? please Guide...
<div>
yolo
</div>
<script type="text/javascript">
var temp = 'jojo';
$.ajax({
url: 'test2.php', //Loco
success: function(data)
{
temp = data;
$('div').html(data);
},
error: function (err)
{
alert('error');
}
});
alert(temp);
var toBeUsedLater = temp; //updated temp value from ajax call
refreshTab();
</script>
This is an asynchronous function. (That's what the A in AJAX stands for.) You are alerting the value of temp immediately , so it is happening before the asynchronous call has finished. If you add
alert(temp);
To the end of your success handler, you will see the value has updated.
AJAX - asynchronous means you are not waiting for response to come and Javascript is interpreted language executed one line after another line. So here the alert(temp) would be executed first and then the success callback as it takes some time to get the response.
1)change
var temp = 'jojo'
to
'temp = 'jojo'
As this is not tied down to the execution context and not limited to files (has pluses and minuses - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
2) The problem is that the alert is called before the callback.
Move the alert into the function. As the ajax is called asynchronously, meaning the success and error functions are called, only when the ajax gets the response back from the server, while the alert you have now will be called right away.
http://javascript.about.com/od/ajax/a/ajaxasyn.htm
$.ajax({
url: 'test2.php', //Loco
success: function(data)
{
temp = data;
$('div').html(data);
alert(temp).
},
error: function (err)
{
alert('error');
}
});
3) alternatively you could set the async of the ajax to false:
What does "async: false" do in jQuery.ajax()?
Which will cause the Ajax call will finish before the next line of code, but it is highly recommended not to do that.
Just add async: false in your ajax options.
I know my title isn't very clear.
For example, this is the structure of my code:
if (foo == something) {
// Ajax call 1, let it be $.ajax("foo1.html") and so on
} else {
// Ajax call 2, let it be $.ajax("foo2.html") and so on
}
How would I test if $.ajax("foo1.html") has actually been run?
Please don't tell me to test if foo == something again. My actual code is much, much more complicated, so please answer the question from the view of the ajax call.
Is this possible at all?
I'm not sure if I understood you right, but jQuery will mix a Deferred object into its jXHR object and you can just check its state.
var resp = $.ajax({});
// somewhere else...
if( resp.state() === 'resolved' ) {
}
Other states are rejected and pending, see http://api.jquery.com/deferred.state/
Of course, you can get all advantages of those Deferred objects aswell, like adding more event handlers for certain things afterwards (.done(), .fail(), etc) or just wait for the promise to fullfil using $.when().
You can set a callback in your ajax call:
$.ajax({
url: "foo1.html"
}).done(function() {
alert('Done!');
});
I would set variable before AJAX call and reset it in the success callback like that :
var isRunning = true;
$.ajax({
url: url,
success: function(resp){
isRunning = false;
}
});
I had similar issues. I used this code:
var isRunning = false; // whether ajax call is running
if(isRunning==false){
isRunning = true;
$.ajax({
// do your stuff
// make sure you set
isRunning = false;
// on success
});
}
Wrap the call in a try catch.
if the call to 'foo1' fails because the method does not exist on the server, in the catch call foo two and then three all the way down until you have exhausted all your fall backs.
If you know the method exists and think it will fail, then set a status on it that can be returned if the server fails then handle the return in the ajax callback.
I'm sure the solution is staring me right in the eyes, but I just cannot see it. I am trying to load an object from an outside file source. I've tried it several which ways using jQuery's built in methods, but keep returning undefined. Is my issue the scope? I need partnerData right where it is because of other dependent methods in my script. I don't want to operate the rest of my site's functions from within the $.get callback. Any help is greatly appreciated, here's the code:
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
});
console.log(partnerData); /* returns undefined instead of object */
});
EDIT:
Thanks for all the feedback everyone. This is the solution I went with:
var partnerData;
$.ajax({
url: 'data/partners.json',
dataType: 'json',
async: false,
success: function(data) {
partnerData = data;
}
});
The reason why you're seeing undefined is because ajax requests are asynchronous by default. This means your get method gets invoked and the code flow moves down to the next statement while the request executes in the background. Your callback function is later invoked when the request completes.
Using callback functions is a common pattern used in situations like this. But you seem to be saying you don't want to do or can't do that. In that case, you could use async: false which would force the request to be synchronous. Keep in mind however, that your code will be blocked on the request and if it's a long-lived request, the user experience will degrade as the browser will lock up.
P.S. You shouldn't need to parseJSON - if response has the correct mime-type set, jQuery will intelligently guess the type and parse the JSON automatically. And in case the server isn't sending back the correct mime-type, you can also explicitly tell jQuery what the expected return data type is; see the dataType argument to $.get() .
One way you might modify your code, to force synchronous requests:
$.ajax({
type: 'GET',
url: 'data/partners.json',
success: function(file){
partnerData = $.parseJSON(file);
//ideally you would perform a callback here
//and keep your requests asynchronous
},
dataType: 'json',
async: false
});
function is proccessed to the end event when ajax is still being proccessed. insert it into callback function
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
console.log(partnerData);
});
});
I would say that your problem is the same of the one that I just solved, if $.get is AJAX! and it is setting a variable, to read that variable outside the callback you need to wait the response! So you have to set async=false!
console.log in synchronous and get is async.
try:
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
test();
});
function test(){
console.log(partnerData);
}
});
This function wont return any value, even though the ajax call goes through correctly
Function:
function queryData(request)
{
var ret = null;
$.ajax({
url: 'ajax.php',
data: 'requestdata='+request,
dataType: 'json',
type: 'post',
success: function (j) {
if(j.ok == true)
return j.data;
else
return 'error';
}
});
return 'error';
}
The ajax function works asynchronously, meaning that it will execute the success function when it gets the result back from the server.
The queryData function will always return 'error' due to the nature of AJAX requests (at least performed this way). You can force the ajax requests to be done synchronously, but this is usually not the desired behavior.
You should add the logic that you want in your success function, rather than trying to return it back. You can pass a named function to the success option if you prefer that. See the jQuery documentation on ajax here.
You can't do that.
AJAX is asynchronous, meaning that your function will return before the server sends a response.
You need to pass the value using a callback, the way $.ajax does.
This function returns a value before the ajax call actually completes. An ajax call is an asynchronous operation, so when you do the $.ajax() call, it immediately returns, your function runs into the return 'error' on line 16 and returns 'error'.
A few milliseconds later the ajax call completes and your success function gets executed, but its return value is not going anywhere.
The success function will be called asynchronously. So first of all the function initialize the ajax request and ended with the last statement return 'error';. After that, after the receiving the response from the server the success function will be called from jQuery. It returns back to the jQuery but will not be used.