Ioannis Kokkinis Ioannis Kokkinis - 6 months ago 55
Javascript Question

return Json.Stringfy result

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

Answer

@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