What does this mean? getData([renderData]); - javascript

Can someone help me understand the logic behind this?
$(document).ready(function() {
getData([renderData]);
});
function renderData(JSON) {
$.each(JSON, function(i, item) {
//logic
}
}
function getData(callBacks) {
var url= '/data/data2';
$.getJSON(url, function() {
}).done(function(JSON) {
if(callBacks) {
for( var i = 0; i < callBacks.length; i++ ) {
callBacks[i](JSON);
}
}
}).fail(function(xhr, status, error) {
//alert(xhr.responseText);
});
}
Is the function renderData getting set as its own parameter?
Thank you.

It's passing the function renderData, inside an array, to another function called getData.
note thats its passing the function and not calling anything, so the array holds a reference to the function and not it's return value, inside getData the renderData function can be called by accessing the first value of the array passed as an argument.
i.e. callBacks[i](JSON); //callBacks[i] is renderData
Looking at getData it would seem that it's been done this way to avoid another layer of nesting inside the ajax calls/responses making the code more readable (once you understand it that is).

getData loads asynchronously some JSON and then calls any amount of callbacks you need (through an array) when everything is loaded. Any callback will be called with the loaded data as first parameter.
In this case, renderData is the only callback given.

Related

json after success return undefined

I am using JS with Angular came to the following problem.
I am getting data from a requestService, so a call the request function and then do something with the data in a 'success' function. Inside this function, everything is fine and I get all my results but as soon as a leave the success function, my results are undefined. I read some other questions/answers about similar problems, and tried other things. However I do not really know how to hand this and wanted to ask this explicitly with a code example:
function loadShips() {
var count = 0;
RequestService.getShips(nelat, swlat, nelong, swlong, timestamp)
.success(function(results) {
var groupedShips = results.aisData.aisGroupedByShipType;
_.each(groupedShips, function(groupedShip) {
_.each(groupedShip, function(ship) {
Markers['marker' + count] = createMarker(ship);
count++;
});
});
console.log(Markers, '#1')
return Markers
});
console.log(Markers, '#2');
return Markers;
}
So anyone could maybe tell me, why Markers at the print out of '#1' are defined and at '#2' are undefined.
Assuming the request is being done asynchronously, the call at #2 is happening before the request's success method is being called. This would explain why the object does not exist yet.
One solution would be to pass a call back method into the factory as a parameter, and then call that method after the request success has occurred. That would look something like this:
function loadShips(callBack) {
var count = 0;
RequestService.getShips(nelat, swlat, nelong, swlong, timestamp)
.success(function(results) {
var groupedShips = results.aisData.aisGroupedByShipType;
_.each(groupedShips, function(groupedShip) {
_.each(groupedShip, function(ship) {
Markers['marker' + count] = createMarker(ship);
count++;
});
});
console.log(Markers, "#1");
callBack(Markers);
});
}
Using this method looks like this:
function myCallback(markers){
console.log(markers, "#2");
//assign markers to something
}
loadShips(myCallback);
As Will P pointed out, with asynchronous functions, the inline code after them will execute first, because the success function is still waiting in the event queue.
in addition to that, Markers is being returned from inside a anonymous function which will not return it as the result of loadShips but will return it inside ajax wonderland, never to be seen.
what you will have to do is have a function that receives the data when it is ready and call that function with the data. I'm assuming things happen after the ships load, those things will have to be called after the anonymous function is done creating Markers.
function loadShips() {
var count = 0;
RequestService.getShips(nelat, swlat, nelong, swlong, timestamp)
.success(function(results) {
var groupedShips = results.aisData.aisGroupedByShipType;
_.each(groupedShips, function(groupedShip) {
_.each(groupedShip, function(ship) {
Markers['marker' + count] = createMarker(ship);
count++;
});
});
doFancyWonderfulThingsInTheOcean(Markers);
});
}

Returning data from looped nested AJAX queries

I have a nested set of ajax calls, something like:
function getSubcategories(cat,callback) {
$.ajax({
url:'myurl.php',
data:'q='+cat,
dataType='json',
success:function(result){ callback(result) }
});
}
function getSubcatElements(subcat,callback) {
$.ajax({
url:'myurl2.php',
data:'q='+subcat,
dataType='json',
success:function(result){ callback(result) }
});
}
function organizeData(cat,callback) {
getSubcategories(cat,function(res){
totals=0;
list=new Array;
$.each(res['subcat'],function(key,val){
getSubcatElements(val,function(items){
$.each(items['collection'],function(key2,val2) {
list.push(val2['descriptor']);
});
totals+=items['count'];
// If I shove "totals" and "list" into an object here to callback, obviously gets called many times
}
// If I return an object here, it doesn't actually have counts from the asynchronous call above
}
function doStuff(cat) {
organizeData(cat,function() {
//stuff
});
So I'm running a looped asynchronous query that's a child of another asynch query, and I want the final result of the child loop without being "lazy". Right now I have it just returning updated results so the numbers change a few times, but I'd like to do it in one fell swoop.
It seems that the obvious place to do it would be to store the results in the asynch and return it after the $.each(), but JavaScript is insane and scoffs at things like obviousness. I feel like this should involve $.Deferred() but the samples I found all seemed like they should trigger after the first iteration ...
(The functions are deliberately separated as there is sometimes reason to use only one or only the other).
Thanks in advance!
Right now, your approach is fine. I want to add following changes in your code
function organizeData(cat, callback) {
getSubcategories(cat, function(res) {
totals = 0;
list = new Array();
totalSubCatItem = res['subcat'].length;
currentSubCatItem = 0;
$.each(res['subcat'], function(key, val) {
getSubcatElements(val, function(items) {
$.each(items['collection'], function(key2, val2) {
list.push(val2['descriptor']);
});
totals += items['count'];
// If I shove "totals" and "list" into an object here to callback, obviously gets called many times
// Here the solution
currentSubCatItem++;
if(currentSubCatItem === totalSubCatItem){
callback(/** pass argument here **/)
}
});
// If I return an object here, it doesn't actually have counts from the asynchronous call above
});
})
}
function doStuff(cat) {
organizeData(cat, function( result) {
//stuff
console.log(result)
});
}
First, you should probably organize your database query on the server side so it's returning a single, multi-plexed result. Rather than calling it lots of times.
Barring that, and assuming you don't know how many sub-categories you're going to call until your category call returns, your best bet is to create a global var that counts up every time it makes a call, and then counts down every time the callback receives a result. Whenever callback fires, counts down, and the new count is zero, do your updates.

How can I get the return value of jquery post function?

function readMemory(ptr, size)
{
$.post("readMemory.php", { ptr : ptr, size : size}, function(data)
{
});
//return "data"
}
Hi, I just want to get data variable as return of readMemory function. Is there any proper way to do this?
The best thing to do is use a callback:
function readMemory(ptr, size, callback)
{
$.post("readMemory.php", { ptr : ptr, size : size}, function(data)
{
callback(data, ptr, size);
});
}
(Note that we have ptr and size being passed to callback as well as data; this is usually good practice.)
So code you were expecting to use readMemory like this:
var data = readMemory(ptr, 100);
doSomethingWith(data);
doSomethingElseWith(data);
...will instead look like this:
readMemory(ptr, 100, function(data) {
doSomethingWith(data);
doSomethingElseWith(data);
});
This is because your readMemory function only starts the POST operation; it returns before the operation completes (the operation is asynchronous).
The improper way would be to make it a synchronous request (which I think would require using the lower level ajax method instead of post).
The proper way would be to forget about returning anything and use your callback function to do whatever you need to do with the data.
AJAX is asynchronous. This means that by the time your readMemory function returns, the result might not be available yet.
The only place that you can reliably consume the results of an AJAX call is inside the success callback:
function readMemory(ptr, size)
{
$.post("readMemory.php", { ptr : ptr, size : size}, function(data)
{
// here and only here you can use data
});
// at this stage there is no way to get the data
}
So the proper way is to not return anything from your function and do whatever you intended to do with those results inside the callback.
var tabela;
function doSomethingWith(response)
{
tabela = response;
}
function get_more(id)
{
var a = id + 11;
var b = id + 21;
$.post("../php/empresas/empresas_tab.php",{id:a, _id:b},function(data){
doSomethingWith(data);
$("#tabEMP").html(data);
//console.error(data);
});
}

AJAX ResponseText as DOM?

Consider the following function using jQuery:
function getVal() {
jQuery.get('/relative/url/', function (data) {
return data.getElementById('myInput').value;
}
}
This is basically what I want to do, but I have no idea how it should be done.
The only methods I know would work involve frames or innerHTML which I can't use because I have to wait for the element to be ready. The only way to do that is to use a callback, and this function must return the value of the element rather than something else.
My logic is likely faulty here, so please feel free to correct me.
First of all, with your current structure you should use a callback to return the value. To parse the HTML string retrieved via AJAX, you can hand it to jQuery and then query it just as usual.
function getVal(callback) {
jQuery.get('/relative/url/', function (data) {
callback($(data).find('#myInput').val());
}, 'html');
}
Then, when you are calling the function getVal, you'll need to provide a callback:
getVal(function(input_val) {
/**
* This code will be run once the GET request finishes.
* It will be passed one parameter - the value of #myInput in the HTML
* response to the request (see getVal function).
*/
alert(input_val);
});
No, you could not do that.. since it is ansync call. What you need is to provide a callback to you code, to return the value
function getVal(callback) {
jQuery.get('/relative/url/', function (data) {
callback(data.getElementById('myInput').value);
}
}
getVal(function (value) {
alert(value);
});
if the it's valid html markup, you can use browse its xml with the selector:
*[id=myInput]
or you can just render the markup on some dummy element in your page and then do you lookup:
function getVal() {
jQuery.get('/relative/url/', function (data) {
dummyNode.innerHTML = data; //not sure data points to responseTxt
return getElementById('myInput').innerHTML;
}
}
You cannot do that unless the elements are added to dom tree.
function getVal() {
jQuery.get('/relative/url/', function (data) {
return $(document.body).append(data).find('#myInput').val();
}
}
Several problems there. First, you cannot return from a callback like that. You would just return to the anonymous function itself, not from the getVal() method.
To solve that, you can return the jXHR object and apply some magic:
function getVal() {
return jQuery.get('/relative/url/');
}
getVal().done(function (data) {
var val = $( data ).find('#myInput').val();
// do something with val
}
I don't know how the structure from data looks like, but it should work that way. If not, its probably because of myInput is on the top level. In that case, replace .find() with .filter().
Oh, alright. I've got it. I don't think I provided enough information. I assumed context was irrelevant. Alright, here's an example depicting my solution.
function getVal() {
$.get('/relative/url/', function (data) {
$.get('relative/url/2', function (data2) {
var data_obj = [];
data_obj.push({
"data_1":data[i].name
}, {
"data_2":$(data).find('#myInput').val()
});
});
}
}

Access array returned from a function - javascript/jquery noob moment

When the form is submitted, I'm calling a function getPosts and passing through a variable str. What I'd like to do is get the data returned from that function.
// when the form is submitted
$('form#getSome').submit(function(){
var str = $("form#getSome").serialize();
var something = getPosts(str);
* This is where I'd like to get the data returned from getPosts()
return false;
});
// get the data
function getPosts(str){
$.getJSON('http://myurl.com/json?'+str+'&callback=?',
function(data) {
arrPosts = new Array();
$.each(data.posts, function(i,posts){
// build array here
});
return arrPosts;
});
};
I've tried many things, but have only gotten 'undefined' returned. I've tried console.log(something);, console.log(getPosts).
I'm missing something very fundamental here. Any help would be greatly appreciated.
EDIT:
What I'm trying to do is create a single function that would get posts. Then different events would call that function. I could then use that data. So one event may be submitting a form, another may be clicking a link, another lazy/endless scrolling. All could use the same getPosts function.
There's a lot of parsing out the results which amounts to a lot of lines of code. Was just trying to find a way to reuse that function. Do you think that would be possible?
$('a.thisLink').click(function(){
getPosts();
get the return from getPosts() and do something with it
});
$('form.thisForm').submit(function(){
getPosts();
get the return from getPosts() and do something with it
});
function getPosts(){
get the posts and return an array
}
Ajax requests are executed asynchronously, the callback function (function (data)) of getJSON is executed when the request ends, and returning a value in that callback has no effect, because is a nested function inside getPosts and its return value is never used.
Actually in your example, getPosts doesn't return anything and it ends its execution before the data is returned.
I would recommend you to work on your submit event handler, if you want to keep the getPosts function, you can introduce a callback parameter:
$('form#getSome').submit(function(){
var str = $("form#getSome").serialize();
getPosts(str, function (data) {
var array = [];
$.each(data.posts, function(i,posts){
// build array here
array.push(/* value to add */);
});
// array ready to work with...
//...
});
return false;
});
function getPosts(str, callback){
$.getJSON('http://myurl.com/json?'+str+'&callback=?', callback);
}
Edit 2: In response to your second comment, you could make another callback, that will be executed when the data has been processed by the first callback, and you can define it when you execute the getPosts function on the submit event handler:
$('form#getSome').submit(function(){
var str = $("form#getSome").serialize();
getPosts(str, reusableCallback, function (result) {
// result contains the returned value of 'reusableCallback' <---
});
return false;
});
function reusableCallback(data) {
var array = [];
$.each(data.posts, function(i,posts){
array.push(/* value to add */);
});
//...
return array;
}
function getPosts(str, callback, finishCallback){
$.getJSON('http://myurl.com/json?'+str+'&callback=?', function (data) {
finishCallback(callback(data)); // pass the returned value
// of callback, to 'finishCallback' which is
// anonymously defined on the submit handler
});
}
Edit 3: I think that the getPosts function and the "reusableCallback" function are strongly related, you might want to join them, and make the code easier to use and understand:
$('form#getSome').submit(function(){
var str = $("form#getSome").serialize();
getPosts(str, function (result) {
// result contains the processed results
});
return false;
});
function getPosts(str, finishCallback){
$.getJSON('http://myurl.com/json?'+str+'&callback=?', function (data) {
// process the results here
var array = [];
$.each(data.posts, function(i,posts){
array.push(/* value to add */);
});
//...
finishCallback(array); // when the array is ready, execute the callback
});
}
Your getPosts function looks incomplete, I'm no jquery expert but should it look something like:
function getPosts(str) {
$.getJSON('http://myexample.com/json?'+str+'&callback=?',function(data){
var arrPosts = [];
$.each(data.posts, function(i,posts){
... build array yada yada ...
});
return arrPosts;
});
}
The problem is that the $.getJSON callback function gets called when the get request returns the data, not inline with your function.

Categories

Resources