JavaScript clearTimeout returns undefined - javascript

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

Related

Not understanding setInterval function

I am reading a project that I have to work and do additional work on, but I don't understand some interval trickery that has been done and not explained by the previous person. That's the code:
var intervalId;
var intervalIdtwo;
$(document).on('click', 'li.mention-individuals', function() {
clearInterval(loadTimer);
var otheridFromSearch = $(this).data('profileid');
var searchImage = $(this).find('img.search-image').attr('src');
var searchName = $(this).find('.mention-name').text();
$('.users-right-pro-pic img').attr('src', searchImage);
$('.users-right-pro-name').text(searchName);
$('.user-info').attr("data-otherid", otheridFromSearch);
xyz(useridd, otheridFromSearch, abc);
$.post('http://localhost/facebook/core/ajax/message.php', {
showmsg: otheridFromSearch,
yourid: useridForAjax
}, function(data) {
$('.msg-box').html(data);
$('.user-show').empty();
$('.top-msg-user-photo img').attr('src', searchImage);
$('.top-msg-user-name').text(searchName);
scrollItself();
})
if (!intervalId) {
intervalId = setInterval(function() {
loadMessageFromSearch(useridForAjax, otheridFromSearch);
}, 1000);
clearInterval(intervalIdtwo);
intervalIdtwo = null;
} else if (!intervalIdtwo) {
clearInterval(intervalId);
intervalId = null;
intervalIdtwo = setInterval(function() {
loadMessageFromSearch(useridForAjax, otheridFromSearch);
}, 1000);
} else {
alert('Nothing found');
}
})
function loadMessageFromSearch(useridForAjax, otheridFromSearch) {
var pastDataCount = $('.past-data-count').data('datacount'); //if no new data, the old messages will be shown
$.ajax({
type: "POST",
url: "http://localhost/facebook/core/ajax/message.php",
data: {
showmsg: otheridFromSearch,
yourid: useridForAjax
},
success: function(data) {
$('.msg-box').html(data);
}
})
$.post('http://localhost/facebook/core/ajax/message.php', {
dataCount: otheridFromSearch,
profileid: useridForAjax
}, function(data) {
if (pastDataCount == data) {
console.log('data is same');
} else {
scrollItself();
console.log('data is not same');
}
})
}
I generally get the code, but the Ifs section with the IntervalId and IntervalIdTwo - I have no clue what it does. Any tips or explanations would be greatly appreciated!
On the surface, the setInterval function is simple: it takes a function and a number n and calls the function (at most) every n milliseconds. It also returns a "handle" that allows you to cancel the repeated invocations by calling clearInterval with the handle.
For instance, here is a function that logs a string to the console:
function sayHello() {
console.log('hello!');
}
We can call it every second (1000 milliseconds) like so:
setInterval(sayHello, 1000);
(You can even try it out in your browser's dev. tools right now! It should print 'hello!' every second)
What if we want to stop printing 'hello!'? If we "hold onto" the return value, we can cancel the repeated invocations:
const handle = setInterval(sayHello, 1000);
(If you're curious, try printing handle!)
To cancel the process, call the clearInterval function with the handle:
clearInterval(handle);
A couple of notes:
In a lot of cases, it is a pain to define a separate function like sayHello, so we would instead use an "anonymous function", like:
setInterval(function() {
console.log('hello!');
}, 1000);
// or
setInterval(() => console.log('hello!'), 1000);
This underscores the fact that setInterval is a higher-order function: it takes another function as one of its arguments. This can take some getting used to, but with practice it becomes second nature.
Depending on how "busy" your browser is, the invocations may not take place at exactly the interval you specify. The delay may be longer than the number you provide, but never shorter (see 3. below for why).
if you really want to grok setInterval you will need an understanding of JavaScript's concurrency model.

Run a function repeatedly 10 seconds after it has completed (JavaScript)

I have a function that uses "post" to get data from the server and process it. Amount of data varies and the function can take a long time to complete (30 seconds). I would like for the function to be called repeatedly but only 10 seconds after it has completed the previous iteration. *Result of the function is stored in a global and is used in the next iteration of the same function.
I've tried setInterval and setTimeout but neither one of those seem to give me the result I'm looking for.
Any thoughts?
function foo(){
$.post( "test.php", { name: "John", time: "2pm" })
.done(function( data ) {
// do your stuff with returned data
// and call itself again...
setTimeout(foo, 10000);
});
}
Wouldn't this approach work?
function a(){
//do stuff
setTimeout(a, 10000); //has to be at the end of the execution. If you're doing things asynchronously that's a different story.
}
function setTimeout() can be used for this. But the method must be invoked for the first time then the function itself invoke the method again.
function method(){
console.log('method invoked');
setTimeout(method, 10000);
}
method();
var $id = 1;
var Interval ;
$(function(){
callAjax();//Starts Interval
});
functoin callAjax()
{
Interval = setInterval(function () {
try {
if($id > 0)
{
$.ajax({
url: _MyUrl + $id,
success: function (calbkData) {
$id = 0;
if (parseInt(calbkData.id) > 0) {
$id = calbkData.id;
OpenMsg(calbkData.id);
}
},
global: false, // this makes sure ajaxStart is not triggered
dataType: 'json'
//,complete: longpoll
});
}
} catch (e) {
// alert(e);
}
}, 10000);
}
This is working very fine, for me.
function Test()
{
//Your code here
setTimeout(Test(),10000);
//Its used to set time interval after your iteration is run
}

Variable undefined after setting interval

I'm wondering why my variable, which is initially set to a value, becomes undefined when accessed from an interval.
Consider the following JQuery:
var TEST = {
DIR: null,
ITV: null,
Init: function () {
this.DIR = 1;
this.Action();
},
Action: function () {
console.log(this.DIR);
if (this.ITV == null)
this.ITV = setInterval(this.Action, 1000);
}
}
$(document).ready(function () {
TEST.Init();
});
The output of this code is as follows:
1
undefined
I understand the 1, because the value of TEST.DIR is set to 1 inside the Init function, which it still is when the Action function is called for the first time.
However, when this function is being called for the second and all other times from the interval TEST.ITV, TEST.DIR is undefined and I don't understand why.
See also this FIDDLE.
Can someone please explain to me what I'm doing wrong or what I'm overlooking?
Thanks!
this.Action is passed to setInterval as function w/o its context so this is not pointing to the instance of TEST any more but defaults to window. Try it like this:
var TEST = {
DIR: null,
ITV: null,
Init: function () {
this.DIR = 1;
this.Action();
},
Action: function () {
console.log(this.DIR);
if (this.ITV == null)
this.ITV = setInterval(function() {TEST.Action() }, 1000);
}
}
$(document).ready(function () {
TEST.Init();
});
http://jsfiddle.net/h44y81Lu/4/
thats because 'this' refers to the window in your set interval, thats why its undefined (there is no window.DIR)
A lot of people have issues with the 'this' keyword, check the MDN docs out

Javascript pass variable through recursive function

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

Execution Requirements for Javascript

I'm new to Javascript, and I'm analyzing the following code. My question is: for the setTimeout() function, how is it being called? It looks to me like it's just being assigned to the variable this.timer, and that it has not yet been called. But the function is executed nonetheless. What am I missing / not understanding? Thank you so much for your help in advance!
$(document).ready(function () {
var validateUsername = $('#validateUsername');
$('#username').keyup(function () {
var t = this;
if (this.value != this.lastValue) {
if (this.timer) clearTimeout(this.timer);
validateUsername.removeClass('error').html('<img src="images/ajax-loader.gif" height="16" width="16" /> checking availability...');
this.timer = setTimeout(function () {
$.ajax({
url: 'ajax-validation.php',
data: 'action=check_username&username=' + t.value,
dataType: 'json',
type: 'post',
success: function (j) {
validateUsername.html(j.msg);
}
});
}, 200);
this.lastValue = this.value;
}
});
});
how is it being called?
The function name (setTimeout) is followed by a ( character, then some arguments, then a ) character.
The first of those arguments is a function expression that is split across multiple lines.
It looks to me like it's just being assigned to the variable this.timer
Its return value (an identifier that can be used with clearTimeout) is being assigned, not the setTimeout function itself.
Executes a code snippet or a function after specified delay.
setTimeout trigger the given function parameter(first parameter) after amount of miliseconds parameter(second parameter).
the return value is:
timeoutID is the numerical ID of the timeout, which can be used later with window.clearTimeout.
Make sure to real all the MDN page
The function is called here:
this.timer = setTimeout(function() {...});
setTimout() executes the anonymous function after the delay and meanwhile returns its numerical ID. this.timer then stores that ID, which can be later with clearTimeout.

Categories