I have the follow code using jQUery's getjson methods
function Share(){
var title = 'Hello';
var description = 'hi description';
var url = "www.facebook.com"
$.getJSON("http://getTitle/1", function(data){
title = data.Name;
});
callShare(title,description,url,imageUrl);
}
function callShare(title,description,url,imageUrl){
window.open(
'http://www.facebook.com/sharer.php?s=100&p[title]='+title+'&p[summary]='+description+' &p[url]='+url+'&p[images][0]='+imageUrl+'','facebook-share-dialog',
'width=626,height=436')}
However, it seems that the method finishes running and does the callShare function before the getJson method has finished running. Would require some help here. I understand that there might be duplicate question here and I apologize but I am not able to apply it here.
Thanks
$.getJSON("http://getTitle/1", function(data){
title = data.Name;
callShare(title,description,url,imageUrl);
});
Being an async function $.getJson() doesn't wait for the response and executes the next line.
If you want to do some things after the response has been received from the server put it in the success function. Like I have mentioned in the code.
if you also want to execute code on error or before sending the request. Use $.ajax() instead
Althoug the question has been answered by Parv but here are some explanation
First of all the correct way to call functions in such senarios
$.getJSON("http://getTitle/1", function(data){
title = data.Name;
callShare(title,description,url,imageUrl);
});
Now the question is why?
$.getJSON is an extension of $.ajax method i.e. Asynchronous, so the browsers expect of waiting for the request to complete by $.getJSON they move on to the next line of codes so that the user dont get stuck with lock browser waiting for a request to complete.
Now what is the solution in that case?
Such Asynchronous requests have a or couple of special methods called call backs, so all you need is to call such methods in those call backs that are required to be called after the successful failed or complete of the request, you will find more in the above link
$.getJSON is just a shorthand for $.ajax. As others pointed out, its an async call which will run in a separate thread(kind of) and rest of the code will keep on executing without worrying for the JSON result.
So you can add a success function which will be called when the async call succeeds. You can use $.ajax too.
$.ajax({
dataType: "json",
url: url,
data: data,
success: callShare(title,description,url,imageUrl),
error: alert('error');
});
I use $.ajax because it gives more clarity over the things that are happening.
Related
I am trying to put a url from an ajax response into a variable in jquery.
I have written the following code:
var thumb = $.ajax({
dataType: 'json',
url: 'https://www.googleapis.com/books/v1/volumes?q=isbn:' + isbn,
success: function(response){
return $(response).volumeInfo.imageLinks.thumbnail;
}}).responseText;
It was my understanding from looking at other answers that I must add .responseText at the end, or the code will continue without waiting for the ajax response.
However, thumb variable remains undefined.
I tried implementing the following solution with relevant changes (As I am passing only one ISBN at a time, there shouldn't be an array. The response should contain only one imageLinks.thumbnail url), but I cannot seem to catch the response correctly.
I looked into other answers, especially this one, but I am still not clear about how to reach the ajax response.
$.ajax is asynchronous, meaning the code will execute completely and the success callback will be fired at a later time.
var thumb is evaluated immediately. Do some reading on "callbacks" and "promises" to get more familiar with this topic.
A solution to your issue is:
function setThumbnail(thumbnail){
// this will evaluate later, when the ajax returns success
console.log('thumbnail gotten!');
var thumb = thumbnail; // do something with in in this function
}
$.ajax({
dataType: 'json',
url: 'https://www.googleapis.com/books/v1/volumes?q=isbn:' + isbn,
success: function(response){
setThumbnail($(response).volumeInfo.imageLinks.thumbnail);
}
});
// This line will evaluate immediately and carry on
console.log('ajax executed');
I threw in some logs for you to help you understand the order of execution here.
I would also note that $(response) looks odd to me, without testing it I think it should probably be just response.volumeInfo....
console.log(response) in the success callback to make sure you understand what data you are getting back.
This question already has answers here:
Easy to understand definition of "asynchronous event"? [closed]
(11 answers)
Closed 7 years ago.
I have the following Javascript and it's returning results out of the order I would expect them.
function getCurrentItems(id){
alert("2");
$.ajax({
url: "somePHPurlthatspitsoutajsonencodedArray.php",
type: "POST",
dataType: "json'",
data: {id:id},
success: function(data){
alert("3");
}
});
alert("4");
}
$(document).on('click', '.eventClass', function(e){
alert("1");
var id = "someID";
var results = getCurrentItems(id);
alert("5");
});
I would think I'd get alerts in the order of 1, 2, 3, 4, 5.
Instead I get them in the order of 1, 2, 4, 5, 3.
I just can't figure out why that success alert (5) fires last?
AJAX is short for asynchronous JavaScript and XML. Asynchronous is the keyword here. I'll use an allegory to explain async.
Lets say you're washing dishes manually. You can't do anything else while doing that, so it is synchronous.
Lets say you put your dishes in a dishwasher. You can do other things, you've delegated the task to the dishwasher, so this is asynchronous. Asynchronous is generally better, because you can do multiple things at one time. Javascript only asyncs when requesting info from the server, as Javascript is single threaded (it only runs on 1 CPU core and can only do one thing at a time on it's own).
A callback is a function that is called when the async task completes. The dishwasher finishes, so now you have to empty it as soon as you complete what you're doing when it finshed.
So in your code, you start the dishwasher, say you're going to alert("3") when the dishwasher finishes running, and then you go alert 4 and 5. Then when the dishwasher finishes/your server returns data, you alert 3 like you said you would.
That make sense?
The reason that you give a success callback function in an ajax request is that the request might take some time to return, but your code can continue running. In this case the ajax request is sent, and the success function is remembered for later, then your code continues (alerting 4 and 5). When the browser receives the response to the ajax request it calls the success function (alerting 3).
The way that Javascript works, only one thread is run per browser tab, so event handlers are not called until any previously running code is completed. Therefore, even if your getCurrentItems function were to take several seconds to complete, by which time the server response had returned, the success function would still not be called until after your function had completed.
Edit: Because an ajax call can take some time, it is not generally desirable to be able to call a function like getCurrentItems which includes an ajax request, and wait for the response. If you do this, then you are likely to leave your browser window unresponsive, and you will have to deal with potential errors from the ajax call. Instead, you should put any code that you wish to run which relies on the ajax result in the success function, or in another function which you call from there. As languages go, Javascript is very good for doing this kind of thing. You could even take a callback function as an argument to getCurrentItems, and run it from the success function.
As others have mentioned, you're getting the results in the order you see because the ajax request doesn't return with it's data and call your success callback until the response is received, but code continues to execute immediately after the $.ajax call.
To get the workflow you're probably expecting, you could use promises, or simply pass in a callback:
function getCurrentItems(id, onSuccess){
alert("2");
$.ajax({
url: "somePHPurlthatspitsoutajsonencodedArray.php",
type: "POST",
dataType: "json'",
data: {id:id},
success: function(data){
alert("3");
onSuccess(data);
}
});
alert("4");
}
$(document).on('click', '.eventClass', function(e){
alert("1");
var id = "someID";
var results = getCurrentItems(id, function(data){
console.log('data',data);
alert("5");
});
});
I've got the following code to call a json web service in a separate functions.js file.
function getMajorGroups(){
var element = $(".item-group-button");
$.ajax({
type:"GET",
url:"localhost:6458/posApplication/getAllMajorGroups",
data:"{}",
contentType:"application/json; charset=utf-8",
dataType:"json",
done:successResult(majorGroups),
fail:errorResult(error)
});
}
function successResult(majorGroups){
var mGroups = response.d;
$("#item-groups").empty();
$.each(majorGroups ,function(){
var h3 = $('h3').append(majorGroups.code);
element.append(h3);
$("#item-groups").prepend(element);
});
}
function errorResult(error){
alert("error");
}
When I run the web page and I use firebug to trace the steps I can see the script is executed. But it does not execute the success or failure code inside the ajax call. Am I doing anything wrong here?
Below is an example of the string which the service return.
{"majorGroups":[{"update":"false","hasMore":"false","status":"A","description":"Beverage","majorGroupId":"48","code":"Beverage"},{"update":"false","hasMore":"false","status":"A","description":"Laundry","majorGroupId":"51","code":"Laundry"},{"update":"false","hasMore":"false","status":"A","description":"Cigarette","majorGroupId":"50","code":"Cigarette"},{"update":"false","hasMore":"false","status":"A","description":"Food","majorGroupId":"47","code":"Food"},{"update":"false","hasMore":"false","status":"A","description":"Health Center","majorGroupId":"52","code":"Health Center"}],"failure":"false"}
$.ajax has no property named failoure. error should be used so it looks like error: errorResult
Besides that check that request is made via Network tab in Chrome dev tools or some similar tool. Check what is in the the raw response and make sure that is what you wanted. If request failed you will see way or at least have error code.
If everything is fine so far then make sure your adding DOM elements when DOM is ready so wrap your stuff with $(function(){ /* your stuff here */ })
Edit:
That's not the way done and fail should be used. jQuery ajax call returns promise.
$.ajax({
url : "..."
/* omitted */
}).done(successCallback).fail(failCallback)
where successCallback can be either function name like your defined succes function or just anonymous function like
.done(function(response){
// do stuff with response
}
I think you should carefully read jQuery documentation.
Also your $.each call is kinda broken - you skipped parameter in function provided to $.each
I've tried Googling this but could not reslove it. It may seem like a really simple issue to others but I'm baffled by it. I have the below code in which I get undefined for the first alert but I still get the correct values in the 2nd alert. BUT if I comment out the first alert (just the line with alert) then the 2nd alert output becomes undefined. Can any one explain why this is and how I may output the 2nd alert correctly without the first one, any Help is greatly appreciated.
function getDetails(ID){
var qArray = [];
$.get('get_Question', {"Id":ID}, function(){})
.success(function(data){
var json = $.parseJSON(data);
qArray.push(json.value1);
qArray.push(json.value2);
});
//First Alert
alert("-> "+qArray[0]);
return qArray;
}
This is the 2nd alert which calls the above method:
var myArray = getDetails(4);
alert("myArray [0]: "+myArray[0]);
You can't return a value, the $.get() call is asynchronous.
You need to defer any operations on qArray until the AJAX call has completed, i.e. inside the callback.
Better yet, use deferred callbacks:
function getDetails(ID) {
return $.get('get_Question', {"Id":ID})
.pipe(function(json) {
return [json.value1, json.value2];
});
}
The .pipe deferred function creates a new promise which will ultimately return the desired array, but only once the AJAX call has completed.
You would then use this like this:
getDetails(ID).done(function(qArray) {
alert("-> " + qArray[0]);
});
Note that $.get() doesn't directly support error callbacks, but with deferred objects you can get access to them:
getDetails(ID).done(function(qArray) {
alert("-> " + qArray[0]);
}).fail(function(jqXHR, textStatus, errorThrown)) {
alert("The AJAX request failed:" + errorThrown);
});
Without this you'd need to build the error handling directly into the getDetails() function and then require some mechanism to tell the rest of the application logic about the error.
NB I've assumed that you don't really need to call JSON.parse() manually - if your web server returns the right Content-Type header then jQuery will do that for you automatically.
Ajax calls happens asynchroniusly, meaning you can't wait for the call to return and get the value. The way to do it is to employ a callback. Your example will become something similar to this:
function getDetails(ID, callback){
$.get('get_Question', {"Id":ID}, function(){})
.success(function(data){
var qArray = [];
var json = $.parseJSON(data);
qArray.push(json.value1);
qArray.push(json.value2);
callback(qArray)
});
}
Calling it will change a bit:
getDetails(4, function (myArray) {
alert("myArray [0]: "+myArray[0]);
});
The First Alert is called before the ajax call is finished, so the variable is still undefined.
This is because the $.get() is done asynchronously. There is no option for $.get() to pass parameter for async calls, so you should use $.ajax() instead and pass a param async: false
The $.get call creates a new asynchronous request for the resource in question.
When you call the first alert it is undefined because the request hasn't been completed yet. Also since you are forced to pause on the alert the request has time to be completed in the background. Enough time for it to be available by the second alert.
The same thing happens when you comment out the first alert. This time the second alert is called before the request is completed and the value is undefined.
You need to either make your requests synchronous or consider continuing execution after receiving the response by using a callback function within the success callback function you have already defined in $.get.
As several others have said, ajax-request are asynchronous. You could however set the async property to false to get a synchronous request.
Example:
function getDetails(ID) {
var result = $.ajax('get_Question', {
async : false,
data : { 'Id' : ID }
});
// do something with the result
return result;
}
I myself would have use a callback function instead beacuse async:false is bad practice and is also deprecated.
You'll need to rewrite $.get to use $.ajax and specify async: false
AJAX is asynchronous: you can't tell when the request will complete. This usually means you need to pass callback methods that will be called with the result of the request when it completes. In your case this would look something like:
function getDetails(ID, callbackFunc){
$.get('get_Question', {"Id":ID}, function(){})
.success(function(data){
var qArray = [];
var json = $.parseJSON(data);
qArray.push(json.value1);
qArray.push(json.value2);
callbackFunc(qarray);
});
}
getDetails(4, function(qArray) {
alert("myArray [0]: "+qArray[0]);
};
Here is the code :-
var quiz;
function startQuiz() {
$.ajax({
url: 'get_quiz/',
cache: 'false',
dataType: 'json',
async: 'false',
success: function(data) {
quiz = data;
alert(quiz[0].q); // I'm able to access quiz here
},
}
);
}
startQuiz();
alert(quiz[0].q); // Not able to access it here.
I'm not able to access quiz here, am I mission something?, Whats wrong with this?
Ajax is assynchronous which can be an unfamiliar concept. Your code will run like this:
1. var quiz;
2. define function startQuiz;
3. call startQuiz;
4. do ajax call (and continue! don't block)
5. alert(quiz[0].q); // Not able to access it here.
-- ajax call comes back
6. quiz = data;
7. alert(quiz[0].q); // I'm able to access quiz here
Ajax is asynchronous, it doesn't block. This means that when you make the ajax call the callback doesn't actually get called until the ajax call returns, it doesn't block and wait. Instead the code will continue on.
Then later when the ajax call returns the data, your callback function will be executed.
Javascript does this by means of an event loop.
See it like this: steps 1-5 are part of the first event. 6-7 are part of the second event.
A cool thing about JavaScript is that in your callback you still have access to anything above it (like the variable quiz) because of scoping. This is called a closure. Your callback function closes around the scope and brings it with him to the next event.
AJAX calls are asynchronous, you should wait for the result to come back from the server. Either do all the work in a callback function or have a look on a promises library (I like Q promises library), which makes waiting for AJAX results very easy.
This is due to the asynchronous nature of JavaScript, once you call startQuiz() it executes and jumps back out and executes your quiz alert().
You have to access your quiz data explicitly after the callback is called to make sure you have access to it.
You also have to worry about scoping, as you may not be actually modifying the same quiz variable.
var quiz,
fetched = false;
$.ajax({
//blah
success : function(data){
fetched = true;
quiz = data;
}
});
setInterval(function(){
if(fetched){
//quiz is populated
}else{
//quiz hasn't be populated yet
}
},50);
Although not a clever example, I'm just trying to get the point across that startQuiz() doesn't wait for the ajax call. The A in AJAX mean asynchronous.
You should give jQuery deferreds a try which ist the preferred way of writing ajax related code since jQuery 1.5: http://javascriptplayground.com/blog/2012/04/jquery-deferreds-tutorial
Once you get the hang of it maybe will be easier to write and understand your code.