How to extract ajax response data from the success callback - javascript

Sorry if this is a duplicate but I couldn't find any satisfying answers in the previous posts.
$(function() {
$.ajax({
url: 'ajax/test.html',
success: function(data) {
// Data received here
}
});
});
[or]
someFunction() {
return $.ajax({
// Call and receive data
});
}
var myVariable;
someFunction().done(function(data) {
myVariable = data;
// Do stuff with myVariable
});
The above code works just fine. However, this ajax request is made on page load and I want to process this data later on. I know I can include the processing logic inside the callback but I don't want to do that. Assigning the response to a global variable is not working either because of the asynchronous nature of the call.
In both the above ways, the 'data' is confined either to the success callback or the done callback and I want to access it outside of these if possible. This was previously possible with jQuery 'async:false' flag but this is deprecated in jQuery 1.8.
Any suggestions are appreciated. Thank you.

You can "outsource" the callback to a normal function, so you can put it somewhere, you like it:
$(function() {
$.ajax({
url: 'ajax/test.html',
success: yourOwnCallback
});
});
somehwere else you can define your callback
function yourOwnCallback(data) {
// Data received and processed here
}
this is even possible with object methods as well

This solution might not be idea but I hope it helps.
Set the variable upon callback.
Wherever you need to process the data, check if variable is set and if not wait somehow.
Try:
$(document).ready(function(){
var myVar = false;
$.ajax({
url: 'ajax/test.html',
success: function(data) {
myVar=data;
}
});
someFunction(){ //this is invoked when you need processing
while(myVar==false){}
... do some other stuff ..
}
});
Or
someFunction(){
if(myVar==false){
setTimeout(someFunction(),100); //try again in 100ms
return;
}
.. do some other stuff ..
}

Related

Javascript sorting out nested functions

So I have script that is for a Bingo game. I'm having a problem running one of my functions inside another function. The idea was to have my checkBingo() function be defined outside of a .click() function. There's some ajax at work, so I'm not sure if that's coming into play here too. Looks something like:
$(document).ready(function(){
function checkBingo() {
$.ajax({
url: '/check-bingo',
type: 'GET',
success: function(data){
return data;
}
}):
}
$('#div').click(function() {
// Some stuff gets done here
$.ajax({
url: '/tile',
type: 'GET',
success: function(data){
// Does some stuff with data, then needs to check if there's a bingo.
var isBingo = checkBingo();
if (isBingo == 'something') {
// Displays something specific on the page.
} else {
// Displays other things on the page.
}
}
}):
});
Where I'm getting hung up, is that isBingo is never getting assigned the returned info. I thought it might have been because the query wasn't running fast enough, so I've tried sticking the variable in a loop until it got something assigned to it and then the console told me that my checkBingo() inside the .click function wasn't defined. I'm not sure if it's just a stupid syntax error on my part or if what I'm doing isn't possible.
Can someone verify that this is indeed possible and that I've probably just got to scour it for the syntax error?
Because this line:
var isBingo = checkBingo();
...is calling an function (checkBingo) which makes an asynchronous call and does not return anything, isBingo will be undefined.
One way to approach this would be to pass a callback function to checkBingo since JavaScript allows functions to be passed around like data, and the function will be called by jQuery when the data is obtained from the server:
function checkBingo(callback) {
$.ajax({
url: '/check-bingo',
type: 'GET',
success: function(data){
callback(data);
}
// or you could just do:
// success: callback,
});
}
// ....
success: function(data){
checkBingo(function (isBingo) {
if (isBingo == 'something') {
// Displays something specific on the page.
} else {
// Displays other things on the page.
}
});
Another approach, which would allow you to continue using your synchronous style (i.e., where checkBingo could return something and you could immediately use it) even though the code is not executed synchronously is by taking advantage of the fact that the later versions of jQuery's Ajax API return a promise object which allows this style of coding:
$(document).ready(function(){
function checkBingo() {
return $.ajax({
url: '/check-bingo.txt',
type: 'GET'
});
}
$('#div').click(function() {
// Some stuff gets done here
$.ajax({
url: '/tile.txt',
type: 'GET',
success: function(data){
var checkingBingo = checkBingo();
checkingBingo.done(function (isBingo) {
if (isBingo == 'something') {
alert('a');
// Displays something specific on the page.
} else {
alert('b');
// Displays other things on the page.
}
});
}
});
});
});
Besides the need to convert a couple of your colons into semi-colons, and add the jQuery $ in front of your "#div" code, two other aspects to note:
I added the ".txt" extension to the Ajax calls in case the extension was merely hidden on your system.
The code $('#div') presumes that there is an element on your page with the ID set to "div". If you want all div elements to be clickable, you would simply need to do $('div').

Keep a javascript variable after an ajax call

I'm new in javascript and jQuery.
I'm using ajax calls to get data from my server. The fact is, I'm losing my javascript variables after the call ..
Here is what I did : the variable is define outside any function and treat in an other function.
var a = 0;
function myfunction(url){
$.ajax({
url: url,
timeout: 20000,
success: function(data){
// Do some stuff
// The a variable is now undefined
},
error: function(){
// Do some stuff
}
});
}
Everything is working fine, the only thing is that I need to keep my variables ... but it looks like it's gone ..
Does anyone know why?
Thanks
You say you're using your variable in another function (but don't show us that function). However, that function is probably running before your AJAX call is complete. This is what "asynchronous" means -- they don't take place at the same time.
To fix this, add some more code inside your success callback, where it will run only after the a variable is changed.
This works and the url does stay in scope. What you should check is if you are getting an error - this will prevent success from running (toss an alert("error"); or something similar in there to test).
I use Firebug in FireFox to help me out.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script type="text/javascript">
var a = 0;
function doSomething (url){
$.ajax({
url: url,
timeout: 20000,
success: function(data){
alert(a);
},
error: function(){
// Do some stuff
}
});
}
</script>
Do it

jQuery Async Issue, Variable Assignment After GET Request

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);
}
});

Callback in jQuery wrapper function

I have written a function that retrieves a html template, then binds data using jQuery.tmpl. I think it's fairly neat and tidy and encapsulates what I need and provides me a reusable function. My question however is can it be improved.
My main concern is what if the $.get method fails, and also how the callBack function is executed.
function Bind(templateURL, templateData, templateTarget, callBack){
var req = $.get(templateURL);
req.success(function(templateHtml) {
$(templateTarget).html(''); //clear
$(templateHtml).tmpl(templateData).appendTo(templateTarget); //add deal
callBack();
});
}
You can pass the result of tmpl() directly to html() to clear your target container and append the new content at the same time. You can also chain the result of $.get() into your success handler to avoid using a local variable:
function Bind(templateURL, templateData, templateTarget, callBack)
{
$.get(templateURL).success(function(templateHtml) {
$(templateTarget).html($(templateHtml).tmpl(templateData));
callBack();
});
}
If $.get() fails, nothing will happen since you do not register an error handler. What that handler would do is up to you, but you might want to display an appropriate message in an alert box or somewhere on the page.
Your second concern is less clear. As it stands, callBack will only be called on success, and without arguments.
You can use $.ajax to assign and error calback. ex:
var jqxhr = $.ajax({ url: "example.php" })
.success(function() { alert("success"); })
.error(function() { alert("error"); })
Check the api http://api.jquery.com/jQuery.ajax/

Javascript - local scope objects not accessible from nested function

I am trying to have a function grab an object from a php file on another page. I'm using the jQuery ajax function to to do the json grab, which is working correctly. The issue is when I try to return that object from the function.
The first time I log the object (from within the success function) it is correct in the console, but the returned object from the function getGantt() logs as "undefined".
How do I get this object out of the function?
My code:
function getGantt(requestNumber){
var ganttObject;
$.ajax({
type: "POST",
url: "get_gantt.php",
data: {request_number: requestNumber},
success: function(returnValue){
ganttObject = $.parseJSON(returnValue);
console.log(ganttObject); //this logs a correct object in the console
}
});
return ganttObject;
}
$(function(){ //document ready function
var requestNumber = $('#request_number').text();
var ganttObject = getGantt(requestNumber);
console.log(ganttObject); //this logs "undefined"
}); //end document ready function
The A in Ajax is an important part of the acronym. Asynchronous JavaScript and XML is asynchronous.
$.ajax({success:someFunction}) means Make an HTTP request and when the response arrives, run someFunction
return ganttObject runs before the response arrives.
You should do anything you want to do with the data inside someFunction and not try to return data to the calling function.
The A in AJAX stands for asynchronous. So the call immediately returns and as soon as it finishes, the success callback is called.
So, simply change your code to use a callback:
function getGantt(requestNumber, callback) {
var ganttObject;
$.ajax({
type: "POST",
dataType: 'json',
url: "get_gantt.php",
data: {request_number: requestNumber},
success: function(returnValue){
callback(returnValue);
}
});
}
$(function() {
var requestNumber = $('#request_number').text();
var ganttObject = getGantt(requestNumber, function(ganttObject) {
console.log(ganttObject);
});
});
Btw, I've also removed this parseJSON stuff - setting dataType to json does the job and is less dirty.
I know why it's not returning it at least. The ganttObject may be in the same scope, but the success function is ultimately running in the readyState callback from the XMLHTTP object, so it's on a different thread than the getGantt function. Can you make the $(function(){... code apart of your success function?

Categories