Javascript pass variable through recursive function - javascript

I am trying to create a recursive function in Javascript. But in order to loop my XML file properly I am trying to pass the right value taken from the XML length and pass it to the setTimeout function.
The problem is that the setTimeout ( setTimeout('cvdXmlBubbleStart(nextIndex)', 3000);
)function does not get the value of nextIndex and thinks it is undefined. I am sure I am doing something wrong.
jQuery(document).ready(function($) {
cvdXmlBubbleStart('0');
});
function cvdXmlBubbleStart(nextIndex) {
$.ajax({
url: "cross_video_day/xml/broadcasted.xml",
dataType: "xml",
cache: false,
success: function(d) {
broadcastedXML = d;
cvdBubbleXmlProcess(nextIndex);
}
});
}
function cvdBubbleXmlProcess(nextIndex) {
var d = broadcastedXML;
//console.log(nextIndex);
var length = $(d).find('tweet').length;
if((nextIndex + 1) < length) {
nextIndex = length - 1;
$(d).find('tweet').eq(nextIndex).each(function(idx) {
var cvdIndexId = $(this).find("index");
var cvdTweetAuthor = $(this).find("author").text();
var cvdTweetDescription = $(this).find("description").text();
if (cvdTweetAuthor === "Animator") {
$('#cvd_bubble_left').html('');
obj = $('#cvd_bubble_left').append(makeCvdBubbleAnimator(cvdIndexId, cvdTweetAuthor, cvdTweetDescription));
obj.fitText(7.4);
$('#cvd_bubble_right').html('');
setTimeout('$(\'#cvd_bubble_left\').html(\'\')', 3000);
} else {
$('#cvd_bubble_right').html('');
obj = $('#cvd_bubble_right').append(makeCvdBubble(cvdIndexId, cvdTweetAuthor, cvdTweetDescription));
obj.fitText(7.4);
$('#cvd_bubble_left').html('');
setTimeout('$(\'#cvd_bubble_right\').html(\'\')', 3000);
}
});
}else{
$('#cvd_bubble_left').html('');
$('#cvd_bubble_right').html('');
}
//broadcastedXMLIndex++;
setTimeout('cvdXmlBubbleStart(nextIndex)', 3000);
}

Using an anonymous function will work because it shares the same scope as nextIndex.
setTimeout(function(){cvdXmlBubbleStart(nextIndex);}, 3000);
The reason that your current code does not work for you is because when you use a string inside of the setTimeout function it uses the Function constructor to create a function based on the string passed (which is similar to using eval and is not best practice). What is worse here is that the function created with Function will not share the same scope as where it was created and thus not have access to nextIndex.

Checkout How can I pass a parameter to a setTimeout() callback? - basically you need to pass an anonymous function to the set timeout call
setTimeout(function(){
cvdXmlBubbleStart(nextIndex)
}, 3000);

Related

Global variable during ajax calls not updating properly

So Javascript is not multithreaded. But I have the following problem.
I use AJAX calls from a function called from setTimeout. I need to know be able to distinguish when there are active AJAX calls before rescheduling the function.
For that I am using 2 global variables. So the code structure is as follows:
setTimeout(some_function, 10000);
window.ajax_running = 0;
window.calls_so_far = 0;
function some_function () {
if(window.ajax_running) {
setTimeout(some_function, 10000);
return;
}
window.ajax_running = 1;
$.ajax({
//various
success: function (data) {
window.calls_so_far = window.calls_so_far + 1;
console.log('Running calls: ' + window.calls_so_far);
if(window.calls_so_far >= SOME_VALUE) {
//we are ok ajax has finished
window.ajax_running = 0;
}
}
Simple code. The problem is that it does not work. I see in the console:
Running calls: 1
So the global variable is not being incremented. It is as is each AJAX call sees the original value 0 and increments it (like as if there were threads).
What am I messing up here? How can I fix this?
When success runs, the ajax call had already finished, so you are not running this call when u add calls_so_far.
I'm not sure why u need the call to be "counted", but if is just the other problem (to call the same function after the first had finished, i would suggest this approach:
var counter;
counter = 0;
function recallSomeFunction() {
setTimeout(some_function, 10000);
}
function some_function () {
$.ajax({
//various
success: function (data) {
if (++counter < SOME_VAL) recallSomeFunction();
//...
},
error: function ( jqXHR, textStatus, errorThrown )) {
recallSomeFunction()
//...
});
}

Uncaught Reference Error: function is not defined

i am using an ajax function to read some contents. Also i want to impliment lazy loading in this content
my code
$(document).ready(function () {
var getparam = '<?php echo $this->paramData;?>';
$.ajax({
type: "POST",
url: "/Index/" + getparam
}).done(function (data) {
console.log(data);
$('#append_here').html(data);
var check = 0;
var int = 0;
var int = setInterval("doThis(check)", 10);
function doThis(check) {
var images = $('img:hidden').length;
if(check >= images) {
clearInterval(int);
}
$('img:hidden').eq(0).fadeIn(10);
check++;
}
});
});
the content coming perfectly. after that there is an error present that doThis is not defind
if any one know about this please help me.
Put doThis() in the global scope, not inside $(document).ready() or inner functions/ callbacks of that.
To say it simply:- move it below the end of the $(document).ready( ...) section.
This kind of error is not entirely uncommon, now that with jQuery we write so much of the Javascript inside the $(document).ready() callback.
setInterval("doThis(check)", 10);
This calls doThis from the global scope since it's called thru an eval-like fashion - and doThis isn't in the global scope.
Try this instead:
var int = setInterval(function(){
var images = $('img:hidden').length;
if(check >= images) clearInterval(int);
$('img:hidden').eq(0).fadeIn(10);
check++;
}, 10);

JavaScript clearTimeout returns undefined

Can someone please explain to me what is wrong with my code below? I am declaring a public variable and setting it to a setTimeout, and if not null, clearing the timeout before it gets set again. When I try to clear the timeout I get undefined so the timeout continues to run.
var usernameCheckTimeout = null;
$(document).ready(function(){
$("#username").on("keyup", function(e){
if($(this).val().length >= 6)
{
if(usernameCheckTimeout != null)
{
clearTimeout(usernameCheckTimeout);
}
usernameCheckTimeout = setTimeout(isUsernameAvailable($(this).val()), 1000);
}
});
});
function isUsernameAvailable(username)
{
$.ajax({
url : "/account/username-check",
method : "POST",
dataType : 'json',
data : {
'username' : username
}
}).done(function(data) {
console.log(data);
});
};
You do not need to do the null check also you need to create a closure around this, otherwise this will refer to not what you think this actually is.
var usernameCheckTimeout;
$("#username").on("keyup", function (e) {
if ($(this).val().length >= 6) {
clearTimeout(usernameCheckTimeout);
var that = this;
usernameCheckTimeout = setTimeout(function () {
isUsernameAvailable($(that).val();
}, 1000);
}
});
Some jsfiddle love like usual.
The timeout is being cleared. The problem is that you are calling your function immediately instead of passing the function to setTimeout.
setTimeout(isUsernameAvailable($(this).val()), 1000);
isUsernameAvailable($(this).val()) will be called and the result of this call will be passed to setTimeout.
You should instead pass a function which calls this function:
EDIT: As #Mark said, you also need to deal with this not being what you expect:
var value = $(this).val();
setTimeout(function(){
isUsernameAvailable(value)
}, 1000);
You have a couple of issues. The first issue, which is huge, is that you are executing isUsernameAvailable($(this).val()) immediately and passing the return value to setTimeout - you need to move this into an anonymous function so it does not execute until the anonymous function is called by the timeout:
usernameCheckTimeout = setTimeout(function () {
isUsernameAvailable($(this).val());
}, 1000);
the javascript timeout functions rely on numeric IDs to function. You should avoid testing for null or undefined or anything else, and instead test for a number:
// leave it as undefined
var usernameCheckTimeout;
...
if (typeof usernameCheckTimeout === 'number') {
clearTimeout(usernameCheckTimeout);
}

calling setinterval with object reference

I have a banner rotator and I wanted to use objects instead of functions so I could make the code more efficient. Anyway I can't seem to get setInterval to work. I think it's got something to do with the object reference. Can anybody explain this? Here's what I've got so far:
window.addEvent('domready', function() {
function set_banner(divid, array)
{
var banner = $(divid);
banner.set('html', '<img src="" alt=""/>');
var banner_link = $(divid).getElement('a');
var banner_image = $(divid).getElement('img');
var delay = 0;
for (var keys in banner1array) {
var callback = (function(key) { return function() {
banner.setStyle('opacity', 0);
var object = array[key];
for (var property in object) {
if (property == 'href') {
var href = object[property];
}
if (property == 'src') {
var src = object[property];
}
}
if (!banner.getStyle('opacity')) {
banner.set('tween', {duration:1000});
banner_link.setProperty('href', href);
banner_image.setProperty('src', src);
banner.tween('opacity', 1);
}
}; })(keys);
setTimeout(callback, delay);
delay += 21000;
}
}
var banner1 = set_banner('banner1', banner1array);
setInterval(function() {set_banner('banner1', banner1array);}, 84000);
var banner2 = set_banner('banner2', banner2array);
setInterval(function() {set_banner('banner2', banner2array);}, 84000);
});
A couple of simple mistake:
var banner1 = new set_banner('banner1');
^ ---------- creates a new object and uses set_banner as the constructor
your code already gets called here
and you get a new object back, which in this case has NO use
....
setInterval(banner1(), 42000);
^----------------- The parenthesis EXECUTE the function
the RETURN VALUE is then passed to setInterval
BUT... banner1() is NOT a function, so this fails
What you want to do in case that you want to call set_banner after 42 seconds AND pass a parameter is to use an anonymous function which then calls set_banner.
setInterval(function() { // pass an anonymous function, this gets executed after 42 seconds...
set_banner('banner1'); // ...and then calls set_banner from within itself
}, 42000);
Something else to consider: http://zetafleet.com/blog/why-i-consider-setinterval-harmful.
(tl:dr Instead of setInterval, use setTimeout.) While I'm not sure that his arguments apply here, it seems like a good thing to get in the habit of avoiding.
function defer_banner(div, bannerArray, delay) {
setTimeout(function() {
setBanner(div, bannerArray);
defer_banner(div, bannerArray, delay);
}, delay);
});

round tripping callbacks

I have an Ajax call with a callback. (I am using YUI for this). The basic call looks like this:
function something() {
var callback1_success = function (o) {…
};
var callback1_failure = function (o) {…
};
var callback1 = {
success: callback1_success,
failure: callback1_failure
};
var callback2_success = function (o) {…
};
var callback2_failure = function (o) {…
};
var callback2 = {
success: callback2_success,
failure: callback2_failure
};
var ajax_params = buildAjaxParams(….);
Y_GET(ajax_params, callback1);
var ajax_params = buildAjaxParams(….); // different stuff
Y_GET(ajax_params, callback2);
} // something
function Y_GET(p_parms, p_callback) {
request = YAHOO.util.Connect.asyncRequest('GET', p_parms, p_callback);
return (request);
} // Y_GET
This all works fine.What I want to do is send the callback to the server, the server will not process the callback parameters and will send them back in the result set.
So, Y_GET will become: Function Y_GET(p_parms, p_callback) {
var parms_to_send = p_parms + “ & passthrough = ” + p_callback;
request = YAHOO.util.Connect.asyncRequest('GET', parms_to_send, local_callback);
return (request);
} // Y_GET
var local_callback = {
success: function (o) {
o.responseText.passthrough.success
},
failure: function (o) {
o.responseText.passthrough.failure
}
}; /* paste in your code and press Beautify button */
if ('this_is' == /an_example/) {
do_something();
} else {
var a = b ? (c % d) : e[f];
}
So, how do I pass a callback function to the server; which returns the name, and call it. If there is another approach, I am open to that, of passing a callback function and acting upon it in the response set.
Thank you.
Off the top of my head, there are a couple of approaches I can think of. eval() is a possibility, but is generally considered something to avoid given the risk of running arbitrary JS code (ultimately this depends on who is providing the string which is being evaled).
I would recommend the following approach:
Create you functions as declarations on a basic JS object.
var Callbacks = {
callback1: function(){ },
callback2: function(){ }
};
Then, use the string returned from your AJAX call as a property indexer into your Callbacks object. I'm not familiar with YUI AJAX requests, but hopefully you get the idea:
var p_callback = function(){
var local_callback = // parse response, get the callback method you want by name/string
Callbacks[local_callback](); // providing arguments as needed, of course
};
YAHOO.util.Connect.asyncRequest('GET', p_parms, p_callback);
By using property accessors on your object you are assured that you are executing only your own callback code, instead of arbitrary JavaScript that may have been included in the response.

Categories