Reputation: 625
I am new to Javascript and currently working on a website, that changes how it looks by itself over time.
One part of this page is a "Typewriter", that writes out a text letter by letter. This is the code for this Typewriter:
function typeWriter(element, txt) {
if (txt.length > 1) {
element.textContent += txt.charAt(0);
var newText = txt.slice(1,txt.length);
setTimeout(typeWriter, 150 , element, newText);
} else {
element.textContent += txt.charAt(0);
}
}
Now I want to wait for the typewriter-function to finish with its text before doing another change to let's say my background-color.
function runThis(){
var line1 = document.getElementById("line1");
typeWriter(line1, "This should be written first, before continuing");
document.body.style.backgroundColor = "blue";
}
To my understanding, the setTimeout makes my typewriter async, so if I do it as in the example above the third line of code will run as soon as the typewriter hits the first setTimeout.
I tried to realize this with the async/await terms and promises. But even after I resolve the promise, my "runThis" function won't continue after the typewriter finishes.
function typeWriter(element, txt) {
return new Promise (function(resolve,reject) {
if (txt.length > 1) {
element.textContent += txt.charAt(0);
var newText = txt.slice(1,txt.length);
setTimeout(typeWriter, 150, element, newText);
} else {
element.textContent += txt.charAt(0);
resolve();
}
})
}
async function runThis() {
var line1 = document.getElementById("line1");
await typeWriter(line1, "papupa");
console.log("waiting over")
document.body.style.backgroundColor = "blue";
}
Can you please help me figure out what's wrong here? Thank you very much
Upvotes: 0
Views: 653
Reputation: 36
You can wrap the setTimeout
in a promise. This will allow you to use the async/await
syntax to express the intention of your code more clearly, almost as if it was running synchronously.
async function runThis() {
var line1 = document.getElementById("line1");
await typeWriter(line1, "papupa");
document.body.style.backgroundColor = "blue";
}
async function typeWriter(element, txt) {
for (var i = 0; i < txt.length; i++) {
element.textContent += txt[i]; // this is shorthand for txt.charAt(i)
await pause();
}
}
function pause() {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 150);
});
}
Upvotes: 1
Reputation: 22474
You're creating more than one promises and only resolving the last one. You could define the recursive function as an inner function, here is an example:
function typeWriter(element, text) {
return new Promise (function(resolve,reject) {
function recursion(txt) {
element.textContent += txt.charAt(0);
if (txt.length > 1) {
var newText = txt.slice(1, txt.length);
setTimeout(recursion, 150, newText);
} else {
resolve();
}
}
recursion(text);
});
}
Upvotes: 0
Reputation: 781004
You can pass the function to run at the end as another parameter.
function typeWriter(element, txt, callback) {
if (txt.length > 1) {
element.textContent += txt.charAt(0);
var newText = txt.slice(1,txt.length);
setTimeout(typeWriter, 150 , element, newText, cb);
} else {
element.textContent += txt.charAt(0);
callback();
}
}
typeWriter(el, "ABCDEF", runthis);
Upvotes: 1