I have this piece of code :
$.getJSON('http://myjsonurl', function(json){console.log(JSON.stringify(json.columns)); });
This returns in the console all I need from my json response. My aim is to get this value into a function so that I can call it in another place. (For example :
"columns" : getColumns();
So I am making a function like this :
function getColumns() {
$.getJSON('http://myjsonurl', function(json){return JSON.stringify(json.columns); });
}
console.log(getColumns()); // and then call the function in the console log expecting to see the same result as before.
But all I get is undefined.
Why?
UPDATE:
This is how I achieved what I wanted. The following code will reinitiate a datatable based on a json response with data and columns (something not supported natively from datatables). The code will reload the table with new query parameters and includes the buttons plugin :
var theurl;
theurl = "http://myjson.json";
function updateQueryStringParameternondt(key, value) {
var table = $('#datatable-buttons').DataTable();
var ajaxurl = theurl;
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
var separator = ajaxurl.indexOf('?') !== -1 ? "&" : "?";
if (ajaxurl.match(re)) {
console.log( ajaxurl.replace(re, '$1' + key + "=" + value + '$2'));
theurl = ajaxurl.replace(re, '$1' + key + "=" + value + '$2');
table.destroy();
TableManageButtons.init();
}
else {
console.log( ajaxurl + separator + key + "=" + value);
theurl = ajaxurl + separator + key + "=" + value ;
table.destroy();
TableManageButtons.init();
}
}
TableManageButtons.init();
var handleDataTableButtons = function() {
0 !== $("#datatable-buttons").length &&
$.ajax( {
url:theurl,
dataType: 'json',
success: function ( json ) {
$("#datatable-buttons").DataTable({
"data" : json.data,
"columns": json.columns,
dom: "Bfrtip",
buttons: [{
extend: "copy",
className: "btn-sm"
}, {
extend: "csv",
className: "btn-sm"
}, {
extend: "excel",
className: "btn-sm"
}, {
extend: "pdf",
className: "btn-sm"
}, {
extend: "print",
className: "btn-sm"
}],
responsive: !0
});
}
} );
},
TableManageButtons = function() {
"use strict";
return {
init: function() {
handleDataTableButtons();
}
};
}();
@guest271314 answer is correct and should guide you to resolve the issues regarding returning undefined from getColumns
method.
I just want to point out some key things here.
First investigate the plunk I created a moment ago. As you can see all the juice here is to manipulate the Deferred object (See here for more). Rougly explaining, the Deferred object can register callbacks, and if you like multiple ones, chain them, and by invoking them can broadcast their state's as well as their responses. It is based to promises design, so such methods return a promise which can be resolved, synchronous or asynchronous (most of times promises are useful in asynchronous operations).
jQuery's asynchronous methods, like $.ajax
return a promise. $.getJSON
is no different, as it calls $.ajax
in the end which, as mentioned returns a jQuery Deferred Promise.
For jQuery's animation
method, see @guest271314 comment below.
More on promise here.
From documentation:
Return a Promise object to observe when all actions of a certain type bound to the collection, queued or not, have finished.
A promise
, when handled is either resolved or rejected. resolve
stands for success responses, as reject
stands for failures.
From documentation we can see that there are methods of Deferred
object to handle success, failure or both.
deferred.done() Add handlers to be called when the Deferred object is
resolved.
deferred.fail() Add handlers to be called when the Deferred object is rejected.
deferred.always() Add handlers to be called when the Deferred object is either resolved or rejected.
So, let's get back to the OP's question. As you can see now from the code:
function getColumns() {
$.getJSON('http://myjsonurl', function(json){return JSON.stringify(json.columns); });
}
There is no way for you to know the getColumns
state, because you do not return the promise
. When using the $.getJSON
handler you essentially handling the response there without emitting the promise object. The getColumns
function of course returns undefined
because there is not sign of return
and by default you get that.
Regarding the deferred.then()
method, with this you can handle a promise also, handling its state as well as its progress. In the example code in Plunker I've posted above I do not care about progress, just only the state, so in the first example the promise is handled with the .then()
method, with the first function to be the success handler and the second function to be the fail handler. Returning the response from them essentially means the promise gets resolved. I return the promise itself as well.
In the commented out section you can see that you can return only the promise if you'd like and resolve the response in always
method
As pointed out by @MiguelBolan , no value is returned from getColmuns()
. return
$.getJSON()
from getColumns()
; use .then()
to access value returned from an asynchronous function
function getColumns() {
return $.getJSON("http://myjsonurl");
}
getColumns().then(function(json) {
console.log(JSON.stringify(json.columns))
}
// handle errors
, function err(jqxhr, textStatus, errorThrown) {
console.log(textStatus, errorThrown)
};
Your getColumns()
function needs to return the variable, at the moment it is only being returned to the function but not out. Try this:
{
function getColumns() {
var ret;
$.getJSON('http://myjsonurl', function(json){
ret = JSON.stringify(json.columns);
});
return ret;
}