clearTimeout on a function that has a paramenter - javascript

I am writing a chat application that can have many chat windows open at once. Every time a window is opened I call a setInterval on my function, update_chat(), that updates an individual chat window. I pass the chat_id to update_chat()
setInterval("update_chat("+chat_id+")",4000);
chat_id is just the id of the chat. So I can have the function update_chat running multiple times on different intervals depending on how many chats are open. Start the chat works fine.
My main question is how can I stop the interval above. I don't want to stop all intervals, just the one associated with a particular chat. I tried this
clearInterval("update_chat("+chat_id+")");
but it didn't do anything.
I tried
var chat_intervals=[]
chat_intervals[chat_id]=setInterval("update_chat("+chat_id+")",4000);
clearInterval(chat_intervals[end_id]);
It didn't stop the interval

clearInterval(docs) takes an interval ID as a parameter to know which interval to clear. setInterval (docs) returns an interval ID when called, so you store that in a var and pass it to clearInterval when you want that one to clear.
//start the interval, store its ID
var interval_id = setInterval( function () { /* do something*/ }, 1000);
//clear the interval
clearInterval(interval_id);
Note that setTimeout (docs) and clearTimeout (docs) work with each other in the same way.
Also note that while setInterval can take a string argument as the function to run, it can also take actual functions (which is highly preferred). So your code could be better written as:
var update_chat_interval = setInterval(function () {
update_chat(chat_id);
}, 4000);
// to clear it later:
clearInterval(update_chat_interval);

Related

Continuously calling function in background

The problem
I am saving pictures in my IndexedDB on the browser. I want to call a function in javascript every 10 seconds to sync the URL's in the IndexedDB to my real database.
It should be down in the backgroud. This means: There should be a function which will be called every 10 seconds to automaticall "sync" the entries in the database.
What i have done
I have already a "sync"-Button/functionality which works fine. This function should be called automatically. But this function in the background should not interrupt or distrubt my main functions in the foreground. For example adding new entries in the indexedDB.
During my research i found the folliwing function:
setInterval(function(){ alert("Hello"); }, 3000);
But it just works alone and not parallel with my "main"-functions.
The ideal solution
The ideal solution should be a function (i have the function already) which will be triggered ever 10 seconds (it don't have to be really 10 seconds, this is just a sample number) but should not disurpt other functions by executing.
If you just want to call your function again and again, try this code using setTimeInterval:
/* The data param is in case you want to pass some param */
var mySynFunc = (data) => {
console.log(`Sync my data: ${data}`);
}
/* This id must be used to stop your function interval */
var id = setInterval(mySynFunc, 3000, 'my-url');
/* If you want to stop your setIntervalFunction use this */
clearInterval(id)

JavaScript setTimeout() duplicates

I'm fairly new to JavaScript/jQuery, but have made a script to change the background picture.
First Script
The first script version works fine and does the following:
creates a setInterval timer that calls function backgroundChange() to run every 7 seconds
decides the next picture URL
sets the background picture
This works great, but the problem is when the website is live, on a slow connection the background picture doesn't load in time for the next timer change.
New Script
So the new version:
creates a setTimeout timer that calls function backgroundChange() to run after 7 seconds
var theTimer = setTimeout(backgroundChange, 7000);
clearsTimeout (surely I shouldn't have to run this?)
window.clearTimeout(theTimer);
decides the next picture URL
waits until the picture is loaded:
then sets the background picture
then adds a new setTimeout timer
$('#testImage').attr('src', imageText).load(function()
{
$('#backgroundTop').fadeIn(timeIn,function()
{
theTimer = setTimeout(backgroundTimer, 7000);
});
});
The problem is that the timer now seems to be called double the amount of times whenever the timer runs and exists in the .load function.
I havent purposely not posted my code yet, as I want to make sure my understanding is correct first, rather than someone just fixing my code.
Ta very much.
Instead of unbinding, you could use a JavaScript closure for the timer function. This will maintain a single timer that is reset every time it is called.
var slideTimer = (function(){
var timer = 0;
// Because the inner function is bound to the slideTimer variable,
// it will remain in score and will allow the timer variable to be manipulated.
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
Then in your code:
$('#testImage').attr('src', imageText).load(function() {
$('#backgroundTop').fadeIn(timeIn,function()
{
slideTimer(backgroundTimer, 7000);
});
});
There should be no need to clear or set the timer anywhere else in your code.
You need to unbind the load handler before you add the next one, since they keep piling up as your code stands. With every iteration, you add an extra handler that does the exact same thing. Use unbind to remove the old handler before you reattach:
$('#testImage').unbind('load');

Jquery/js, taking a value from textfield and using ajax to send it to the server

I need to use this plugin: http://jstepper.emkay.dk/Default.aspx to be able to use "mousewheel" value incrementation.
This plugin offers a function onStep, which will run a my own function each time a value is incremented. Now it would be real simple to just send new value to the ajax function, but that would mean hundreds, if not thousands of POST requests, lots of mysql inserts/updates, it would be very messy...
I am trying to implement somekind of a timer that would take the value from the textfield, wait 1000milliseconds and then post it to the server, whenever a user should scroll for more values, it would cancel the previous timeout and start counting again.
This introduced two problems, first - if a user scrolls one textfield and then immediately starts scrolling the next textfield the previous textfield data wouldn't be sent, because the new field would take the control of the timer.
And secondly, I couldn't get the values anyway I tried, this is probably easy to fix, I just have to figure out how to...
So I'm hoping that someone might help me in this, because I am stomped.
$(".basket_input").jStepper({onStep:function(){ajaxSleeper(this.value, this.id)}});
var timer = 0;
function ajaxSleeper(val1,val2){
clearTimeout(timer);
timer = setTimeout(function(){
ajaxUpdate(val1,val2);
//alert('updated!');
}, 3000);
}
HTML
<td><input class="basket_input" size="5" maxlength="6" type="text" value="" name="1939" id="1939" /></td>
The easiest thing to do would be to use $.data to set the timer and keep using the context of the actual object.
jQuery
var $basket_input = $(".basket_input");
$basket_input.jStepper({
onStep: function() {
ajaxSleeper.call($basket_input.get(0)); // Call the function using the
// element as the context
}
});
function ajaxSleeper() {
// Get any timer that could be set for this element
var thisTimer = $(this).data('timer');
// Clear it if there is one
if (thisTimer) clearTimeout(thisTimer);
// We need this as the context in setTimeout will change to "window" object
// Yet we want to reference this object in the setTimeout
var $that = $(this);
$(this).data('timer', setTimeout(function() {
ajaxUpdate($that.val(), $that.attr('id'));
//alert('updated!');
}, 3000);
);
}
Two possible solutions.
If you haven't seen Underscore.js, you should. They have a _.throttle() that will do exactly what you want, along with a million other useful things.
If you don't want to use another library, you're close.
var timer;
var fireOffMyRequest = function()
{
// ... FIRE EVERYTHING! ...
};
var somethingThatGetsFiredOften = function()
{
clearTimeout(timer);
timer = setTimeout(fireOffMyRequest, 4000);
};
That limits to 4 seconds; you could change the 4000 to reflect whatever you want the throttle limit to be.
edit: I forgot to address your timer issue. Store off the timer onto the HTML element:
$(this).data('timer', timer);

jQuery infinite function execution

We want to know if it is possible to have a function using jQuery to inspect a number of elements and, depending on the types assigned to them by one click, perform other functions. Basically, a function that would run forever, while the user does not refresh the page.
The idea is not to depend on events clicks to perform a function, but the classes assigned to a specific element.
For example:
$("td.gantt").each(function() {
if($(this).hasClass("oper")) {
//execute a serie of functions
}
if($(this).hasClass("preop")) {
//execute a serie of functions
}
});
The above is executed once, and we need to run all the time.
// define a function...
function ganttEach() {
$("td.gantt").each(function() {
// ...
});
}
// ...repeat it once every second
window.setInterval(ganttEach, 1000);
You can't "let it run all the time" (like, in a while(true) loop) because JavaScript is single-threaded and blocking the thread means your other code will never run. setInterval() makes sure there are necessary "gaps" for other code to execute.
setInterval() returns an ID that you can store in a variable and feed to clearInterval() at some point to make it stop again.
If you want to make sure that every new iteration of your function starts only after the previous one has really finished, use setTimeout() instead:
// define a self-repeating function...
function ganttEach() {
$("td.gantt").each(function() {
// ...
});
window.setTimeout(ganttEach, 1000); // calls itself again in one second
}
// ...initiate self-repeating function
ganttEach();
You should probably include some way to stop the endless repetition here as well, like introducing a flag that's checked before the setTimeout() call.
You can run your check every few milliseconds, say 50ms, using setInterval
window.setInterval (function () {
// do checks here
}, 50);
You might end up using a lot of CPU power if your checks are too frequent, or too complicated.
It is possible, with setInterval. My advice would be to select the element outside of the repeating function so as to minimize the overhead.
An infinite loop would lock the browser UI, as it is a single threaded environment. Set interval, however let you add actions to the UI stack which will be executed after a given period of time. You can specify this period in the second parameter of setInterval.
// select the element outside
// to minimize overhead
$gantt = $("td.gantt");
// define a repeating action
setInterval(function() {
$gantt.each(function() {
if($(this).hasClass("oper")) {
//execute a serie of functions
}
if($(this).hasClass("preop")) {
//execute a serie of functions
}
});
}, 100); // repeat interval: 100ms
I am not sure exactly what you are trying to do, but have you tried setInterval? It will keep running if that is what you really want.
window.setInterval(function () {
// add your jQuery here
}, 100);

Is it OK to call clearInterval inside a setInterval handler?

I have a piece of Javascript that checks for a condition (via an AJAX call) every n seconds. If that condition is true, it stops checking. I have implemented it in the following way:
var stopTimer;
var timerId = setInterval(function() {
/* Make Ajax Calls and set stopTimer */
if (stopTimer) {
clearInterval(timerId);
}
}, 10000);
However, I find erratic behaviour: Works sometimes, but at other times, it keeps checking forever. I have checked that (as much as is possible) there is no error in any part of the code.
I am therefore suspecting that calling clearInterval inside a setInterval handler might be the culprit. Is that right? Is it OK to call clearInterval inside a setInterval handler?
Thank you for your attention
It's safe. The issue is probably to do with stopTimer not being set as you expect.
I don't think there will be any issue with your code unless the AJAX function is erroneous. You have to take care of the success and error callbacks of the AJAX function so that there won't be any issue with the loop not being stopped.
Also I think you are constantly polling the server for a response and then doing the appropriate action. You can use Reverse AJAX to do this kind of process.
Make sure you're not inadvertently re-using the same timer name elsewhere in your code which would result in you always stopping the second timer to be defined.
Either give the timer a unique name, or scope it to a function
var timerForAjax = setInterval(function() {
/* Make Ajax Calls and set stopTimer */
if (stopTimer)
{
clearInterval(timerForAjax);
}
}, 10000);
I was careless enough to call my timer interval and didn't realize I was creating two timers in the same scope both called interval. Blamed iOS8 for about an hour until I realized that that was nothing to do with it.

Categories