Kārlis Janisels Kārlis Janisels - 1 month ago 12
Javascript Question

How to restart recursive function in JS using setTimeout and clearTimeout?

I am trying to build simple chat module in CodeIgniter.

var last_id = 1;

$(document).ready(function(){
loadMsgs();
$("#content").focus();
$("form#chatform").submit(function(){

$.post("<?php echo base_url() ?>index.php/msg/update",{
message: $("#content").val(),
con_id: <?php echo $con['conversation_id'] ?>
}, function(){
$("#content").val("");
$("#content").focus();

loadMsgs();
});
return false;
});
});

function loadMsgs() {
$.getJSON('<?php echo base_url() ?>index.php/msg/backend/<?php echo $con['conversation_id'] ?>/' + last_id, function(json) {
$.each(json, function(i,val){
//console.log(val.id);
if(<?php echo $login_id ?> == val.sender_id){
$("#messagewindow").append('<div class="bubble"><p>' + val.msg + '</p></div>');
} else {
$("#messagewindow").append('<div class="bubble bubble-right"><p>' + val.msg + '</p></div>');
}
});
updateScroll();
var newIndex = json.length-1;
if(typeof(json[newIndex]) != 'undefined'){
last_id = json[newIndex].msg_id;
}
setTimeout('loadMsgs()', 4000);
});
}
function updateScroll(){
var element = document.getElementById("messagewindow");
element.scrollTop = element.scrollHeight;
}


I have function loadMsgs that use $.getJSON to call for controller that grabs last messages from database and then append them to #messagewindow. Last thing in callback is setTimeout so hat is updated every 4 seconds.

On submit action I post new message to controller and in callback call loadMsgs again. As a result of that every time I submit new message additional call is added which is not good.

I tried to clearTimeout adding global variable id, changed
var id = setTimeout('loadMsgs()', 4000);
and
added clearTimeout(id);
before calling loadMsgs again after submiting another message. However nothing changes.

Answer

If you have a global variable id, and then in your handler you're calling

var id = setTimeout('loadMsgs()', 4000);

you're never touching the global id.

By having var again in your handler, you're defining another (and another...) copy of id, setting a timeout on each. Var defines a NEW variable, and it looks like you're doing that repeatedly. Take out the var in the handler:

clearTimeout(id);
id = setTimeout('loadMsgs()', 4000);