简体   繁体   中英

Function using setTimeout throws on subsequent calls

I'm trying something easy, a typewriting effect:

 var i = 0; var txt = "eco eco" var speed = 1; function typeWriter(idtxt) { if (i < txt.length) { document.getElementById(idtxt).innerHTML += txt.charAt(i); i++; setTimeout(typeWriter, speed); } };
 <button class="remo-btn" onclick="typeWriter('demo')"> <p id="demo"></p>

When I hardcode the id, the code works as intended:

document.getElementById("demo").innerHTML += txt.charAt(i);

But when I pass the id like this:

document.getElementById(idtxt).innerHTML += txt.charAt(i);

It only returns the first letter, in this case, "e" (from echo ).

Can somebody help me?

You forgot to pass in idtxt while calling typeWriter in the setTimeout :

 var i = 0; var txt = "eco eco" var speed = 1000; function typeWriter(idtxt) { if (i < txt.length) { document.getElementById(idtxt).innerHTML += txt.charAt(i); i++; setTimeout(() => typeWriter(idtxt), speed); } };
 <button class="remo-btn" onclick="typeWriter('demo')"> <p id="demo"></p>

This is happening because the idtxt variable is out of scope after the first call to typeWriter . You can pass the parameter to subsequent calls to typeWriter by passing it as the first argument of setTimeout . Like so:

setTimeout(typeWriter, speed, idtxt);

You can read more about setTimeout here: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout

And you can learn more about why this is necessary here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

 var i = 0; var txt = "eco eco" var speed = 1000; function typeWriter(idtxt) { if (i < txt.length) { document.getElementById(idtxt).innerHTML += txt.charAt(i); i++; setTimeout(typeWriter, speed, idtxt); } };
 <button class="remo-btn" onclick="typeWriter('demo')"> <p id="demo"></p>

Also, you probably meant for speed to equal 1000 (1 second). The delay of setTimeout is measured in milliseconds.

ES6 offer other way for that.

for example with Promise management:

 const delay = ms => new Promise(r => setTimeout(r, ms)), txt = 'Hello, world;'. async function typeWriter(idtxt) { const elm = document.getElementById(idtxt) for await (let letter of txt) { elm.textContent += letter await delay(500) } }
 <button class="remo-btn" onclick="typeWriter('demo')">remo-btn</button> <p id="demo"></p>

change setTimeout(typeWriter, speed ); to setTimeout(typeWriter, speed, idtxt );
you are missing to send idtxt argument

PS cahnge also var speed = 1000; 1s == 1000ms

 var i = 0; var txt = "eco eco" var speed = 1000; function typeWriter(idtxt) { if (i < txt.length) { document.getElementById(idtxt).innerHTML += txt.charAt(i); i++; setTimeout(typeWriter, speed, idtxt ); } };
 <button class="remo-btn" onclick="typeWriter('demo')"> <p id="demo"></p>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM