Create a unique function name on the fly for shared timer - javascript

I'll start with the exact nature of the problem and then give some background. I am trying to name a function -threadTimer- and give it a random unique identifier, such as 'threadTimer'+ID. A randomly generated ID would work fine. Then, I need to use setInterval on it, to make it fire repeatedly and therein lies my coding problem. I have tried every variation of new, function, function as an object and I just can't get my head around it. You'll notice that the function I have created is an object and perhaps this is where I'm going in circles.
OK, the background I mentioned. threadTimer is fired by a master timer co-ordinating several threads. That's why you'll see I have generated a 'global' object for reference elsewhere. similar HTML entities can fire threadTimer at the same time, hence my requirement to make each instance unique.
window['GlblThreadExe'+ID]=setInterval(function(){threadTimer(elid,parent,lft,top,diameter,point,bStyle,color,grp,startTime,size,ID,counter,div,divwth,divht,wthIncrement,htIncrement,lftStart,topStart,lftIncrement,topIncrement)},interval);
function threadTimer(elid,parent,lft,top,diameter,point,bStyle,color,grp,startTime,size,ID,counter,div,divwth,divht,wthIncrement,htIncrement,lftStart,topStart,lftIncrement,topIncrement){
// more code
}
In truth, I think its the volume of parameters that I'm passing that's confusing my syntax. Any help appreciated

Avoid polluting window
Generally instead of polluting the global namespace you can store your setInterval ids in some variable
let intervalIds = {}
intervalIds['GlblThreadExe'+ID] = setInterval(function()...)
If really necessary, then store intervalIds to window
window.intervalIds = intervalIds;
Wrap your anonymous function
When you create the "clock", do not call setInterval directly:
Here, createTimerWithId will return a function which calls threadTimer
Dirty id generation
Use a timestamp, and mix it with some random stuff. Or better use a UUID
setInterval(createTimerWithId(), 1000)
function createTimerWithId(){
let id = Date.now()+Math.random(); //no lib, oneliner. good enough to debug
return function(){//the same function you gave to setInterval in your example
threadTimer(id, ...)
}
}
We can do better
In 1. we generated an id on the fly and thus
your code is not testable (id will always change(well except if you mock Math and Date...)).
your id is ugly (a float...)
it will be hard to know from which setInterval you come from
instead, give it the ID.
function createTimerWithId(ID){
return function(){//the same function you gave to setInterval in your example
threadTimer(ID, ...)
}
}
window['..'+ID] = setInterval(createTimerWithId(ID));
shorter version being
window['..'+ID] = setInterval((id=>{
return function(){
threadTimer(id, ...)
}
})(ID),1000);

Related

Is creating a function to do a small repeated task an anti-pattern?

I am trying to learn best practices for programming and want to keep my code as clean as possible, but also maintainable. For example, I am running a program that waits for each element to be created.
a.waitForElementToAppear(50000);
b.waitForElementToAppear(50000);
c.waitForElementToAppear(50000);
Now, I added a function so I can easily change the 50000 without having to manually edit each one:
function waitForElement(element) {
element.waitForElementToAppear(5000);
}
and have changed the above code to:
waitForElement(a);
waitForElement(b);
waitForElement(c);
Is it an anti-pattern to create a new function to call for a relatively small task? Is there a better approach?
Is it an anti-pattern to create a new function to call for a relatively small task?
No, it is absolutely fine! Although you're right that your function is so small that it hardly gains anything.
Is there a better approach?
To achieve your goal of easily changing the shared argument value, you could alternatively (not necessarily "better") also put it in a variable:
const time = 50000;
a.waitForElementToAppear(time);
b.waitForElementToAppear(time);
c.waitForElementToAppear(time);
Last but not least, that code still is a bit repetitive. Another option would be a loop (although those three items are just about the threshold for a loop being sensible):
for (const element of [a, b, c]) {
element.waitForElementToAppear(5000);
}

Javascript performance, recreate function or bind then?

My application is a local server that receive about 2/3 requests per seconds.
At each request, it stores and update data, process some calculation, update view (react), ...
I would like to know what is faster, when i have to use closures :
Simply create the function where I need it:
var parentValue = 'ok';
randomAsyncFunction(function() {
console.log(parentValue);
}
Create a "global" function and then bind the callback with needed values:
function testCallback(value) {
console.log(value);
}
var parentValue = 'ok';
randomAsyncFunction(testCallback.bind(undefined, parentValue));
Note: theses pseudo-codes will be executed 2/3 times per seconds. For the second example, the testCallback function will be created once, and the bind will be called instead of re-creating the function.
So, is it better or worse to use the second example ?
Both bind and the closure function expression do create a new function object. Their difference in performance will be negligible. If you really care enough, run a benchmark with your actual code and real data to see which solution is faster.
In your case, you should only care which solution is more readable and maintainable. None is strictly better or worse than the other, you have to decide yourself which one you like better.

Ok to call document.querySelector( ) a bunch

If I have multiple instances of the following lines of code through out my js file:
document.querySelector('#IdName').play();
document.querySelector('#IdName').pause();
Is it a good idea to create a function and pass it the IdName(IdName will change in various parts of the code)? I know what it does but I'm really just curious if it's a good practice to call document.querySelector( )a bunch of times in the file or put it in a function where I only call it twice to perform the play and pause actions.
If you constantly need the same element, change the function to take a DOM node, and store the element in a variable instead
function doStuff(elem) {
elem.play();
}
function stopStuff(elem) {
elem.pause();
}
var element = document.querySelector('#IdName');
doStuff( element );
// later
stopStuff( element );
That way you only get the element once, and avoid unneccesary DOM lookups
The best approach is to cache that query in a variable so you don't need to search the DOM each time.
For an ID selector this time saving is likely minimal but for more complex collections can help
var $el = document.querySelector('#IdName');
$el.play();
$el.pause();
It is good practice to write code that is reusable, so in that case a function is better practice. If the function only contains 1 line of code and you call it many times, it is still preferable because then if you ever decide to update that line of code or add more code, it's centralized and you change in one place only.
As far as actual execution is concerned, these are the same:
document.querySelector('#IdName1').play();
document.querySelector('#IdName1').pause();
document.querySelector('#IdName2').play();
document.querySelector('#IdName2').pause();
document.querySelector('#IdName3').play();
document.querySelector('#IdName3').pause();
vs
playpause("#IdName1");
playpause("#IdName2");
playpause("#IdName3");
function playpause(idname){
document.querySelector(idname).play();
document.querySelector(idname).pause();
}
In addition to Steve's answer, also note that if you are using the same one twice in a row:
document.querySelector('#IdName').play();
document.querySelector('#IdName').pause();
then it is a better practice to do:
var thing_with_play_and_pause = document.querySelector('#IdName');
thing_with_play_and_pause.play();
thing_with_play_and_pause.pause();
This reduces the number of queries you have to make. Some IDEs (PyCharm for instance) will complain if you don't because it is less efficient.

What is the role of variables (var) in Javascript

I am currently learning JavaScript and I am wondering what is the role of the variables (var).
In the example bellow, on the last two lines we first define a variable "monCompte" in which we call "john.demandeCaissier(1234)". Then we use console.log(monCompte) to print the result on the screen. What I don't understand is why do we first need to define the variable "monCompte" to call "john.demandeCaissier(1234)". Why can't we just do something such as:
console.log(john.demandeCaissier(1234));
Example
function Personne(prenom,nom,age) {
this.prenom = prenom;
this.nom = nom;
this.age = age;
var compteEnBanque = 7500;
this.demandeCaissier = function(mdp) {
if (mdp == 1234) {
return compteEnBanque;
}
else {
return "Mot de passe faux.";
}
};
}
var john = new Personne('John','Smith',30);
var monCompte = john.demandeCaissier(1234);
console.log(monCompte);
Thank you for you answers.
Yes, you can inline your function call and avoid the need for a variable. However, if an error occurs on that line, it becomes harder to debug:
var monCompte = john.demandeCaissier(1234);
console.log(monCompte);
vs
console.log(john.demandeCaissier(1234));
in the second example, there are several different modes of failure that would not be apparent in a debugging session. When split over two lines, some of those failures become easier to track down.
Second, if you wanted to reuse the value returned by john.demandeCaissier(1234) (the author might have shown this), then a variable becomes very useful indeed.
In my opinion, it's a worthy pursuit to perform only a single operation per line. Fluent-style advocates might disagree here, but it really does make debugging considerably easier.
You could definitely do that, but in more complex programs you will need to store variables for several reasons:
Shortening Long Expressions
Imagine if you saw this code somewhere:
console.log((parseInt(parseFloat(lev_c + end_lev_c)) - parseInt(parseFloat(lev_c + start_lev_c)) + 1));
BTW I got that from here
Wouldn't it be so much simpler just to split that expression up into different variables?
Storing Data
Let's say that you take some input from the user. How would you refer to it later? You cannot use a literal value because you don't know what the user entered, so do you just call the input function again? No, because then it would take the input a second time. What you do is you store the input from the user in a variable and refer to it later on in the code. That way, you can retrieve the value at any time in the program.
If you are a beginner, you might not see any use for variables, but when you start writing larger programs you will start to use variables literally in almost every line of code.
Variables exist to store data. They're useful because instead of invoking an operation over and over again, which is criminally inefficient, they allow you to invoke an operation once, and then use that result where necessary.
And that's for all languages, not just JavaScript.
Variables are structures that store some value (or values). They're only that and you could probably do all your code (or the majority of it) without them.
They help you organize and add some readability to your code. Example:
alert(sumNumbers(askNumber()+askNumber()));
takes a lot more effort to read/understand then this:
var firstNumber = askNumber();
var secondNumber = askNumber();
var total = sumNumbers(firstNumber + secondNumber);
alert(total);
Sure it's longer but it's more readable. Of course you don't have to use var for everything, in this case I could just hide the total.
Another common use for variables is "caching" a value.
If you had a function that sums like 1 million values, if you keep calling it for everything, your code would always have to do all that hard work.
On the other hand, if you store it on a variable the first time you call it, every other time you need that value again, you could just use the variable, since its a "copy" of that calculation and the result is already there.

Function inside an if statement inside a function

I currently have the following code:
function someFunctionThatRunsOnce(identifier){
if (var < 1){
runSomeOtherFunction(identifier);
var++;
}
}
The variable will not increment when var < 1 is true. It stays at 0 and does not increase. When I move the variable increment statement about runSomeOtherFunction(), it then works fine.
What I want to know is:
1) Why is this happening? Why is running the second function disabling the increment?
2) Is there a better way to do this? I need to run this function this way exactly once, under a set of very specific circumstances. The function that runs is used elsewhere using different parameters for (identifier).
Please keep things simple I am a super noob and do not know jQuery and only really simple use of JS.
a big issue is that "var" is not a valid variable name, it's a reserved keyword.
you can easily use your wrapper as a namespace to store the state of being called or not:
function someFunctionThatRunsOnce(identifier){
if (!someFunctionThatRunsOnce.spent){ //not run yet?
someFunctionThatRunsOnce.spent=true; //set as run
runSomeOtherFunction(identifier); //run real workload
}
}
this lets you avoid global variables and curtails the possibility of runSomeOtherFunction() accidentally changing the state of the spent tracker property.

Categories

Resources