Reputation: 51
I'm trying this javascript code
var txt = "", txtLen = 0, elem='';
var speed=90;
function write( obj ) {
txt = obj.str;
speed = obj.speed;
elem = obj.elem;
txtLen = txt.length;
setTimeout("loop()", 300);
}
var c=0;
function loop() {
if( c <= txtLen ){
document.getElementById(elem).innerHTML+=txt.charAt(c);
c++;
setTimeout("loop()", speed);
} else {
c=0;
}
}
but in html when i call write function two time its prints only last one, like this-
<font id="o"></font><br>
<font id="oo"></font>
<script>
write({
elem:'o',
speed:90,
str:'Hello'
});
write({
elem:'oo',
speed:90,
str:'World'
});
</script>
Can anyone tell me please, where the error is??
Upvotes: 0
Views: 64
Reputation: 3866
Because you are executing the printing asyncronously, so when you print the first one, the second one already modified your vars.
What you are facing is called impure functions.
Impure functions
All of them which modifies its external environment, usually called side effect.
Any function that uses a non-local variable is potentially impure, for example:
function impure(x) { return x + a; }
The idea to solve it is transform your impure functions into pure functions. What does it mean? A pure function is a function which does not modify its external enviromnent.
Pure functions
All of them which does not modify its external environment, for example:
function pure(x, a) { return x + a; }
Below you have your example working:
<font id="o"></font>
<br>
<font id="oo"></font>
<script>
function write( obj ) {
setTimeout(() => {
loop(obj, 0);
}, 300);
}
function loop(obj, c) {
if( c <= obj.str.length ){
document.getElementById(obj.elem).innerHTML += obj.str.charAt(c);
setTimeout(() => {
loop(obj, c + 1);
}, obj.speed);
}
}
write({
elem:'o',
speed:90,
str:'Hello'
});
write({
elem:'oo',
speed:90,
str:'World'
});
</script>
As you see, loop
function takes nothing from its external environment any more.
Sharing vars is not a good option when you are working asyncronously.
Hope It helps you.
Upvotes: 0
Reputation: 21
This should work
function loop(obj, c) {
if( c <= obj.str.length ){
document.getElementById(obj.elem).innerHTML += obj.str.charAt(c);
setTimeout(loop, obj.speed, obj,c+1);
}
}
function write( obj ) {
setTimeout( loop, 300, obj, 0);
}
The setTimeout function optionally can take variables that will be passed to the callback function
Upvotes: 1