Multiple javascript timeouts - problem with live data fetching - javascript

I am building a real-time system which (with a use of websockets) updates a table with live data of different frequencies (can be 3 times per second, can be once every 2 seconds - dependant on the type of data).
I am currently struggling to find a way of letting the user know when a particular field has not been updated in the last 5 seconds. That is, if no new data is fetched, I shouldn't keep the old value there, but rather change it to '--' or something similar.
After a long way to the javascript, final function which updates fields looks like that (extremely simplified):
function changeValue(data){
var fieldId= data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
}
This function gets called each time a field needs to be changed. I've got between 2 and 40 different fields (dependant on the user) that are changed.
What is the best way of setting timers in order to change the values of the fields to '--' every 5 seconds, if no update has been made?
I would be really grateful for some tips,
Thanks,
Karol.

Since you want to indicate timeout on a per-field basis, you have two obvious options:
Have a global interval timer that ticks over fairly frequently and looks through all of your fields for a timeout.
Have independent timers for each field which just deal with that field.
I think on balance I prefer (1) to (2), because we're only dealing with one interval timer then and it makes the housekeeping simpler.
Since IDs in documents must be unique, we can use your field ID values as a key in a hash (an object) to store last updated times. This is kind of a spin on the previous answer but works on a per-field basis. So here's how we'd set those last updated times:
var lastUpdatedTimes = {};
function changeValue(data){
var fieldId= data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
lastUpdatedTimes[fieldId] = new Date().getTime();
}
Then you set up an interval timer to check each of them.
function checkFieldsForTimeout(){
var now = new Date.getTime();
// For each ID in lastUpdatedTimes, see if 'now minus
// last updated' is > 5000 and is so, set the field
// text to '--' and remove that entry from the last
// updated list with "delete lastUpdatedTimes[itemId]".
}
Should a timed-out field spring back to life, the "--" will be replaced by some real text again.
By deleting the last updated time from "lastUpdatedTimes" whenever we put "--" into a field, we make sure that the interval timer isn't wasting time processing fields that have already been timed out.

This answer was extended to handling multiple fields after the comment by #Andrew (please see also his answer).
Introduce a property updatedTime, which holds the last time the data was updated, in each data. A periodic timer checks updatedTime for all data and updates the text field if appropriate. The check has to be twice as often as the detection period. Your function changeValue() updates updatedTime and the text field.
function checkData() {
var now = new Date.getTime();
for "each data" {
if (now - data.updatedTime >= 5000) {
var fieldId = data.fieldId;
$('span#'+fieldId).text('--');
}
}
}
function changeValue(data) {
var fieldId = data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
data.updatedTime = new Date.getTime();
}
// Install periodic timer to check last updates:
setInterval(checkData, 5000 / 2); // interval = half the required detection period

Related

How to randomise string from an array without having the same output twice in a row

I am trying to generate a random string output from an array that's getting triggered at random times. The issue that I am facing now is, sometimes the same output comes out twice in a row, or even more than two times. I wanted the output to be different every single time it gets triggered. I don't want the next output to be the same as the very previous output. Please take a look at the code below. Thanks!
function randAnnouncement() {
var lastIndex, ann = ["one", "two", "three"];
let randomAnnouncement = ann[Math.floor(Math.random() * ann.length)];
//speakTTS(randomAnnouncement);
console.log(randomAnnouncement);
}
function init() {
var myFunction = function() {
randAnnouncement();
var rand = Math.round(Math.random() * (5000 - 1000)) + 500; // generate new time (between x sec and x + 500"s)
setTimeout(myFunction, rand);
}
myFunction();
}
init();
What you are asking for is a random string generator without replacement on the last selected value. The only way to do this is to store the last value somewhere so you can exclude it or repeat the random selection if the same value is selected.
As the web is stateless (i.e. doesn't remember the last value when the page reloads), I suggest that you create a transient or store the last value and read it again before each test.
Another option is to increase the size of the dataset from which your random selection is made. In your example of only 3 values, there is a 33% chance that the same value is selected again. Whereas if you had say 200 values then there would be only 0.5% change of a repeat value occurring.
I hope that this helps you get a solution that you can use.

Numbers not adding to LocalStorage

I want do add numbers to a pre-existing amount in LocalStorage. What I find after is that it is indeed recognised that there is a new amount, but when I refresh the page it doesn't keep to LocalStorage...
//Just making an index
localStorage.setItem("currentUser",10)
//This makes currentUser.whatever into something viable
var currentUser = (JSON.parse(localStorage.getItem('usersArray')))[localStorage.getItem("currentUser")];
//I add the number to the pre-existing amount
currentUser.goldAmount = currentUser.goldAmount + 50;
//For reference 100 is a pre-existing amount for goldAmount, so it should now be 120. It does alert that although when i refresh the page and do it again its not 200, but still 150. It resets back to 100 every restart...
alert(currentUser.goldAmount);
Appreciate the Help :)
Try checking whats inside your JSON and the currentUser object.
Note that if the JSON contains
{"currentUser":{"goldAmount":10}}
Than you will need to read it like
currentUser.currentUser.goldAmount
variable in-json var requested var

Meteor: How to set a number based on the number of checked boxes within a section

I currently have a multi-section form, with a number of checkboxes. What Im trying to do, is show the number of checked boxes, next to the total. I have total showing up just fine, but I cant for the life of me figure out a way to loop over the inputs, successfully find the :checked, and print that number out.
I think the main thing causing me issues, is that it needs to update every time a new box is checked. Heres some of the code.
Event Handler
'click input[type=checkbox]': function(){
Session.set('selectedPlayerCount', n);
Session.get('selectedPlayerCount');
}
The goal here is to set the number of selected players, and pass it to the template/helper.
Helper
countSelected: function(){
n = 0;
n++;
var selectedPlayerCount = Session.get('selectedPlayer');
return selectedPlayerCount;
}
Within the helper I'm attempting to iterate every time the event is triggered, and as a result increase the value by one. I'm aware that resetting n back to 0 is going to cause some issues, and I know that needs to be changed one the rest is figured out. I just cant figure out where the variable needs to be set in order to provide a default value.
Template
<header>
<p>{{ countSelected }}</p>
</header>
All I'm trying to do here for now is to print out the value rendered by the helper. I don't believe this is causing any issues.
TL;DR - How to count number of checked inputs within a section of a form, and for each one, increment a value, and then return it every time its changed.
I'm new to this but maybe this will serve: define your account to zero in a session variable, each time you select a checkbox you increase the value of your session variable
Session.set("countPlayersChecked", 0);
Template.proof.helpers({
countSelected: function () {
return Session.get("countPlayersChecked");
}
});
Template.proof.events({
'click input[type=checkbox]': function (event) {
if($(event.target).is(':checked'))
Session.set("countPlayersChecked", Session.get("countPlayersChecked")+1);
else
Session.set("countPlayersChecked", Session.get("countPlayersChecked")-1);
}
});
Hope it serves.

Javascript: Storing the current time's timestamp value

Is there a way to store the current timestamp in a Javascript variable? The reason is I want to compare Javascript's current time value with a Django time variable, and whenever the time matches, it will send a popup notification.
I guess reloading the page maybe every 3 seconds or so would work, but that seems extremely inefficient.
I'm not sure exactly what you're trying to do here. It's not likely the times will ever match exactly unless you check every millisecond, but you can always check when the time is greater than the django variable, or within a certain range. This will check the time every three seconds.
var django = // Create a javascript date object from django timestamp here
var interval = setInterval(function(){checkTime()}, 3000);
function checkTime() {
var d = new Date();
if (d >= django) {
//Do something here
clearInterval(interval);
}
}

How to make timed queue in javascript

Ok. I don't have a code for this question. I am asking this because I am new to javascript. I would like to know how to create a timed queue in JS. Here is the trick.
I have a combobox. The combobox has extjs data store behind and its getting updated with new data every 5 seconds, i.e the combo will get new row entries.
The row entries can be of three types 1,2 and 3. There can be several rows of same type but with different row id. Each row will be removed from the combo if there is no update for 5 minutes. This means if I get new row from the store with type 3 it will stay in the combo for 5 minutes. If the same row appears (with the same id and type) in the new data fetched the 5 minutes timer gets reset and again counts 5 minutes. And so forth.
How to achieve this functionality in javascript.
Please write comments if not understood.
Here is an example:
row_1 type1 5 min timer start
row_2 type1 5 min timer start
row_3 type3 5 min timer start
row_2 type2 5 min timer start
This is an example of the current data fetched. After 3 minutes I get this data.
row_3 type3 5 min timer start
the rest of the rows timers continue until 5 min limit is reached but for row three the timer gets reset and it will stay in the combo for the next 5 minutes.
You're going to have to keep track of two things here: The actual item, and when it was last updated (or, more accurately, the timeout event which will update it.
timeouts = [];
elems = [];
function updateElem(no){
//Do your update on elems[no]
clearTimeout(timeouts[no]);
timeouts[no] = setTimeout(function(){ removeElem(no) }, 5*60*1000 );
}
function removeElem(no){
//Remove the element.
}
This demonstrates the base concept. There are much better ways to keep everything tied together, but the basic idea is:
Set a timeout on the object to remove it after five minutes
When updating an object:
Clear the previous timeout
Set a new timeout
Because JS isn't truly multi-threaded, you don't have to worry about concurrency issues, as long as you have your scoping figured out.
Check this documentation to see how the timeout events work in a fuller sense.
Somewhere else:
function ComboRemoval(id)
{
Lookup your combobox (document.findelementbyid perhaps)
Find element with value "id"
remove it
}
When adding an element to the combo box:
Add the element
setInterval(function() { ComboRemoval(1234)}, 300000); //FIXED AS PER COMMENTS BELOW
setInterval will fire function ComboRemoval in 5 minutes, and it will remove ID 1234 from the box.
300000 = 5 minutes (1000 = 1 second, 60 x 5 = 300 seconds, 300 x 1000 = 300000)
Building upon #Gherkin's answer, using jQuery:
function addOption(key, text, timeout) {
var el = $("<option></option>")
.attr("value",key)
.text(text);
​$('#test').append(el);
setTimeout(function() { el.remove(); }, timeout);
}
Now you can call:
addOption("value", "Text for option", 2000);
See it in action: http://jsfiddle.net/um9Cu/
You could expand addOption() to also lookup an existing item with the key and extend the timeout, or whatever you need to do.
You need to make use of a recursive function that calls setTimeout()
Example:
function myFunc() {
var minutes = 5;
//do stuff here
setTimeout(function() { myFunc() }, minutes*60000 };
}
When called myFunc() will fire and then call itself on a 5minute timer. The rest of the programs logic is 100% dependent on end-results.
I solved this problem by usign session. The newest data was written in session, so the new requests were according to the data in session. I used php and js in concert. Js was reading trough php session

Categories

Resources