Count the return function - javascript

How can i count or check the length of the return function
function leavereminder() {
$.getJSON("<?=base_url()?>home/leavereminder",
{},
function(data) {
if(data.length != 0) {
for(x=0; x<data.length; x++) {
var lblm = document.createElement('div');
lblm.innerHTML = '<label>'+data[x]+'</label>';
lblm.className = 'alert alert-info';
document.getElementById('notifbody').appendChild(lblm);
}
}
var b = data.length;
});
}
I want my variable b to be global variable so i can fetch the length

You cannot return back values from async calls. Instead you can use callbacks to know when async call is completed. In your example :
leavereminder(function(length) {
console.log(length); // This will get you your data length immediately after JSON call is completed.
});
function leavereminder(callBack) {
$.getJSON("<?=base_url()?>home/leavereminder",
{},
function(data) {
if(data.length != 0) {
for(x=0; x<data.length; x++) {
var lblm = document.createElement('div');
lblm.innerHTML = '<label>'+data[x]+'</label>';
lblm.className = 'alert alert-info';
document.getElementById('notifbody').appendChild(lblm);
}
}
// Instead of this : var b = data.length;
callBack(data.length); // This will send the length back(alternate for return)
});
}
Problem with using Global variables is you will never know when the call completes(unless you add an observer but why not keep it simple?)

It's not clear what you mean by "check the length of the return function," but I think you mean check the value of b. In that case, just declare b outside your callback, like this:
var b = 0;
function leavereminder() {
$.getJSON("<?=base_url()?>home/leavereminder",
{},
function(data) {
if(data.length != 0) {
for(x=0; x<data.length; x++) {
var lblm = document.createElement('div');
lblm.innerHTML = '<label>'+data[x]+'</label>';
lblm.className = 'alert alert-info';
document.getElementById('notifbody').appendChild(lblm);
}
}
b = data.length;
});
}
P.S. You should use a more descriptive variable name than b - this name is hard to debug and may well conflict with other scripts on the page.

If you want b to be global then you need to initialize it outside the function. Then b will accessible by leavereminder().
var b;
function leavereminder() {
$.getJSON("<?=base_url()?>home/leavereminder",
{},
function(data) {
if(data.length != 0) {
for(x=0; x<data.length; x++) {
var lblm = document.createElement('div');
lblm.innerHTML = '<label>'+data[x]+'</label>';
lblm.className = 'alert alert-info';
document.getElementById('notifbody').appendChild(lblm);
}
}
b = data.length;
});
}

Write it in hidden html input field with jquery and use it later.
In your ajax call:
$('#count_var').val(data.length);
Your html to collect the count:
<input type="hidden" name="count_var" id="count_var" />

Related

$.when apply for single request

I am trying to use $.when apply in my code. However, it seems that the format return is different for single and multiple request. How can i cater for it?? I am trying not to have another if else outside of it.
$.when.apply(null, apiRequestList).then(function () {
for (var i = 0; i < arguments.length; i++) {
var value = arguments[0];
}
});
This is what i do not want to do.
if (apiRequestList.length === 1) {
$.ajax({
});
} else {
$.when.apply(null, apiRequestList).then(function () {
for (var i = 0; i < arguments.length; i++) {
var value = arguments[0];
}
});
}
You can simply convert arguments into an array, when the length of apiRequestList is 1:
$.when.apply(null, apiRequestList).then(function() {
var _arguments = Array.prototype.slice.call(arguments);
if (Array.isArray(apiRequestList) && apiRequestList.length === 1)
_arguments = [arguments];
for (var i = 0; i < _arguments.length; i++) {
var value = _arguments[i][0];
console.log(value);
}
});
Live Example on jsFiddle (since we can't do ajax on Stack Snippets):
function x(a) {
return $.post("/echo/html/", {
html: "a = " + a,
delay: Math.random()
});
}
function doIt(apiRequestList) {
$.when.apply(null, apiRequestList).then(function() {
var _arguments = arguments;
if (Array.isArray(apiRequestList) && apiRequestList.length === 1)
_arguments = [arguments];
for (var i = 0; i < _arguments.length; i++) {
var value = _arguments[i][0];
console.log(value);
}
console.log("----");
});
}
doIt([x(1), x(2), x(3)]);
doIt([x(4)]);
Example output (it'll vary because of the Math.random()):
a = 4
----
a = 1
a = 2
a = 3
----

Deferred objects with multiple getJSON calls that depend on each other

I am making 3 get JSON calls in myFunction() that gets called on a button click. 2 of these getJSONs depend on each other for their execution. It basically parses through 10 web pages and collects some data. With this data it will go to another page and collect some other data. I want to display "DONE" at the end of myFunction so the user knows that we have finally got all data and the search operation is complete. However these calls, I think, are asynchronous, so I use deferred objects. But even though I pass all calls to $.when.apply(call1,call2,call3), it displays the "DONE" before any data is printed on the console. Once it prints "DONE", then it starts to print the results. How can I modify my code so that I would be able to display "DONE" only when myFunction has ran completely for all 10 pages and has printed all data on the console.
var call1 = [];
var call2 = [];
var call3 = [];
function myFunction() {
data3 = [];
url = ''; // some URL here
call3.push($.getJSON(url, function(data4) {
data3 = data4;
}));
for (var page = 1; page < 10; page++) {
(function(page) {
url = 'http://example.com/' + page;
call1.push($.getJSON(url, function(data1) {
for (var num = 0; num < data1.standings.results.length; num++) {
(function(num) {
url = 'http://example.com/' + data1.entry[num];
call2.push($.getJSON(url, function(data2) {
for (var i = 0; i < 15; i++) {
(function(i) {
console.log(data3.ele[(data2.p[i].element) - 1].x);
return;
}
})(i);
}
})
);
})(num);
}
})
);
})(page);
};
$.when.apply(call1, call2, call3).then(function() {
console.log("DONE");
});
}
I was finally able to solve this problem. As mentioned in the comments, we need to chain various promises and the function structure should match the structure of the when command. So, in the function as call1 was pushed first, I need to call the when command for call1 and then nest the subsequent commands and so on.
var call1 = [];
var call2 = [];
var call3 = [];
function myFunction() {
data3 = [];
url = ''; // some URL here
call3.push($.getJSON(url, function(data4) {
data3 = data4;
}));
for (var page = 1; page < 10; page++) {
(function(page) {
url = 'http://example.com/' + page;
call1.push($.getJSON(url, function(data1) {
for (var num = 0; num < data1.standings.results.length; num++) {
(function(num) {
url = 'http://example.com/' + data1.entry[num];
call2.push($.getJSON(url, function(data2) {
for (var i = 0; i < 15; i++) {
(function(i) {
console.log(data3.ele[(data2.p[i].element) - 1].x);
return;
}
})(i);
}
})
);
})(num);
}
})
);
})(page);
};
$.when.apply($, call1).then(function(){
$.when.apply($, call2).then(function(){
document.getElementsByName('output')[0].value+="Search Completed"+'\r\n';
});
});
}

Javascript Callback in for Loop

My problem is that I'm having a Function A which calls at one point another function, let's call it Function B (getChildContent) and needs the return value of Function B in order to proceed. I know that it's because of Javascripts Asynchronous Nature, and i tried to solve it with a callback. But i can't get it work properly.
FunctionA(){
//some Code.....
else {
for(i in clustertitles) {
if(S(text).contains(clustertitles[i])) {
var parent = {};
parent.ClusterName = clustertitles[i];
parent.Functions = [];
var str = '== ' + clustertitles[i] + ' ==\n* ';
str = S(text).between(str,'.').s;
var caps = parseFunctions(str);
for(y in caps) {
//var content = getChildContent(caps[y]);
getChildContent(caps[y], function(content) { //Function call
var child = {};
child.FunctionName = caps[y];
child.Content = [];
child.Content.push(content);
parent.Functions.push(child);
console.log(content);
});
}}}
}
function getChildContent (capname, callback) {
t = capname.replace(' ', '_');
bot.page(t).complete(function (title, text, date) {
var str = S(text).between('== Kurzbeschreibung ==\n* ', '.').s;
if(str === undefined || str === null || str === '') {
throw new Error('Undefined, Null or Empty!');
}
else {
var content = {};
str = parseTitles(str);
content.Owner = str[0];
content.Aim = str[1];
content.What = str[2];
content.Who = str[3];
content.Steps = str[4];
content.Page = 'some URL';
callback(content);
}
});
}
So in Function A I'm trying to call getChildContent from a for-Loop and pass the current string from caps-array. For each String in caps-array getChildContent() makes a http request over a node.js module and retrieves a string. With this string i'm building an object (content) which is needed in Function A to continue. However the 'console.log(content)' in Function A just prints out the object which is created with the last string in caps-array, but for many times. E.G. if caps-array has 5 entries, i get 5 times the object which is created with the last entry of caps-array.
How can i manage the loop/callback to get every time the right object on my console?
Your loop should call another function that preserves the value of y, something like this:
FunctionA(){
//some Code.....
else {
for(i in clustertitles) {
if(S(text).contains(clustertitles[i])) {
var parent = {};
parent.ClusterName = clustertitles[i];
parent.Functions = [];
var str = '== ' + clustertitles[i] + ' ==\n* ';
str = S(text).between(str,'.').s;
var caps = parseFunctions(str);
for(y in caps) {
yourNewFunction (y, caps, parent);
}}}
}
function yourNewFunction (y, caps, parent) {
getChildContent(caps[y], function(content) { //Function call
var child = {};
child.FunctionName = caps[y];
child.Content = [];
child.Content.push(content);
parent.Functions.push(child);
console.log(content);
});
}
function getChildContent (capname, callback) {
t = capname.replace(' ', '_');
bot.page(t).complete(function (title, text, date) {
var str = S(text).between('== Kurzbeschreibung ==\n* ', '.').s;
if(str === undefined || str === null || str === '') {
throw new Error('Undefined, Null or Empty!');
}
else {
var content = {};
str = parseTitles(str);
content.Owner = str[0];
content.Aim = str[1];
content.What = str[2];
content.Who = str[3];
content.Steps = str[4];
content.Page = 'some URL';
callback(content);
}
});
}
There are 2 ways to do so.
Put the loop inside a function, execute your callback after the loop is done. (Problematic if you are doing async call inside the loop.
function doLoopdiloopStuff() {
for() {
}
callback();
}
The other way, the way i prefer looks like this:
for(var i = 0; i < stuff || function(){ /* here's the callback */ }(), false; i++) {
/* do your loop-di-loop */
}
In another example:
for (var index = 0; index < caps.length || function(){ callbackFunction(); /* This is the callback you are calling */ return false;}(); index++) {
var element = caps[index];
// here comes the code of what you want to do with a single element
}

Passing JSON parse value to a global variable

$(function() {
var global_datalength = 0;
leavereminder();
alert(global_datalength);
});
function leavereminder() {
$.getJSON("<?=base_url()?>home/leavereminder",
{},
function(data) {
if(data.length != 0) {
for(x=0; x<data.length; x++) {
var lblm = document.createElement('div');
lblm.innerHTML = '<label>'+data[x]+'</label>';
lblm.className = 'alert alert-info';
document.getElementById('notifbody').appendChild(lblm);
}
}
var datalength = data.length;
});
global_datalength = datalength;
}
I have a global variable of global_datalength and i want to replace it with my return json
but when i alert my code it always 0. it didnt pass my global_datalength = datalength. because when outside of json function my data.length is unknown
Remove the var keyword on global_datalength to make it global.
You can also use window.global_datalength.
Another way is to declare the variable outside the jQuery ready function.
Your JSON call is async. That means the alert will be called before the JSON has returned from the server.
What you can do is:
function leavereminder() {
$.ajax({
dataType: "json",
url: "<?=base_url()?>home/leavereminder",
async: false,
success: function(data) {
if(data.length != 0) {
for(x=0; x<data.length; x++) {
var lblm = document.createElement('div');
lblm.innerHTML = '<label>'+data[x]+'</label>';
lblm.className = 'alert alert-info';
document.getElementById('notifbody').appendChild(lblm);
}
}
global_datalength = datalength;
},
});
}
Need to keep global_datalength outside the jQuery function.
Also since leavereminder is asynchronous, you might want to keep global_datalength = datalength; inside the function(data)
var global_datalength = 0;
$(function () {
leavereminder();
});
function leavereminder() {
$.getJSON("<?=base_url()?>home/leavereminder", {},
function (data) {
if (data.length != 0) {
for (x = 0; x < data.length; x++) {
var lblm = document.createElement('div');
lblm.innerHTML = '<label>' + data[x] + '</label>';
lblm.className = 'alert alert-info';
document.getElementById('notifbody').appendChild(lblm);
}
}
global_datalength = data.length;
alert(global_datalength);
});
}

unable to read values into global array variable using javascript

I am working on a javascript code that looks like the following. I am only showing the basic skeleton of the code first.
var array = [];
function mainFun()
{
A();
}
function A()
{
//some code
B();
//code to print all values in "array"
}
function B()
{
C();
}
function C()
{
//some code
//push elements one by one in "array"
for (var i=0; i<10; i++)
{
array.push(i); //something on these lines
}
}
I know this code seems bizarre but this is exactly the situation I am working on. Thanks to Javascript's function level scoping (as against the regular block-level scoping), I am unable to access and print all the elements in A() that have been pushed in the array in C(). So how can I make my array variable work like a true global variable that has knowledge of what elements were pushed into it?
Ok, here is my original source code (I don't know how the dummy code worked though!)
var allLinks = {}; //set of all internal and external links
var Queued = [];
var crawlingURL;
var Crawled = [];
var xmlHttp = null, originURL, maxHops = 0, currentHop = 0;
function changeText(){
var tabID, sourceURL;
chrome.tabs.query({currentWindow: true, active: true}, function(tabs){
console.log(tabs[0].url);
document.getElementById('URL').innerHTML="URL of Current Page : "+tabs[0].url;
tabID = tabs[0].id;
sourceURL = tabs[0].url;
Queued.push(sourceURL); //push the origin link the Queued array to begin crawling
beginCrawl(sourceURL);
});
}
document.addEventListener('DOMContentLoaded', function () {
changeText();
});
function beginCrawl(url)
{
originURL = url;
maxHops = 2;
currentHop = 1;
var queueIndex = 0;
//httpGet(originURL);
while(queueIndex<1) //(currentHop <= maxHops)
{
crawlingURL = Queued[queueIndex];
//allPages[crawlingURL] = {url:url, state:"crawling", level:0, host:startingHost};
httpGet(crawlingURL);
Crawled.push(crawlingURL);
queueIndex++;
for(var j = 0; j < Queued.length; j++)
{
console.log(j+". "+Queued[j]+"\n");
}
}
}
function httpGet(theUrl)
{
xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, true );
xmlHttp.send( null );
xmlHttp.onreadystatechange = ProcessRequest;
}
function ProcessRequest()
{
if ( xmlHttp.readyState == 4 && xmlHttp.status == 200 ) // xmlHTTP success
{
var container = document.createElement("p");
container.innerHTML = xmlHttp.responseText;
var anchors = container.getElementsByTagName("a");
var list = [];
for (var i = 0; i < anchors.length; i++)
{
var href = anchors[i].href;
var exists = 0;
// to check for duplicate entries in the list
for(var j = 0; j < Queued.length; j++) // remove duplicates
if(Queued[j] == href)
exists = 1;
if (exists == 0)
{
Queued.push(href);
document.getElementById('printORGLinks').innerHTML += href + "<br />";
}
}
}
}
I am unable to get print the values in my Queued Array ! (As you may understand, this is a preliminary code for a web crawler of some sort. I need to get the list of all URLs pushed into the Queued array).
This works as you've entered it - fiddle here http://jsfiddle.net/LmFqq/1/
Output
some code executing in A()
some code executing in B()
adding elements in C()
printing in A()
[0,1,2,3,4,5,6,7,8,9]
Code
var array = [];
var el = document.getElementById('output');
mainFun();
function log(msg) {
el.innerHTML += msg + "<br />";
}
function mainFun()
{
A();
}
function A()
{
log("some code executing in A()");
B();
log("printing in A()");
log(JSON.stringify(array));
}
function B()
{
log("some code executing in B()");
C();
}
function C()
{
log("adding elements in C()");
for (var i=0; i<10; i++)
{
array.push(i); //something on these lines
}
}

Categories

Resources