Alim Bolar
Alim Bolar

Reputation: 531

SetTimeout is confusing me and I need to be able to promisify it

I have 2 separate div elements and I have a function that defines each element and is supposed to only act on the element. so when i call typeField(name,element1) it should type into only element1 and similarly then I call typeField(address,element2) it should type into only element2.. but currently if you check my codepen implementation it's mixing the characters and I am not sure why.

Also after this I need to figure a way out where I can get the name to type in first and then after that's done I need to start the typing of the address. My assumption is I need to promisify the functions and then call them as async/await. Is that the right approach? or am I overthinking this?

So my 2 questions are

  1. What am I doing wrong in my code that's mixing up the contents in elements innerHTML?
  2. Once that's resolved how can I make the first element type first and on completion start the next one

Any help in resolving this would be appreciated.

This is the link to my Codepen

https://codepen.io/alimbolar/pen/Rwjoqbm?editors=1111

const typewriter1 = document.getElementById('typewriter1');
const typewriter2 = document.getElementById('typewriter2');
const name = 'Alim Bolar';
const address = "Some part of the world";
const currentLocation = "Bali, Indonesia";
const profile = "Frontend Development, Backend Development, WordPress Development"
let content = "";
let i = 0;

function typeField(x, element) {
  if (i < x.length) {
    alphabet = x.charAt(i);
    content = content + alphabet;
    element.innerHTML = content;
    i++;
    setTimeout(function() {
      typeField(x, element)
    }, 500);
  }
}
typeField(name, typewriter1);
typeField(address, typewriter2);
<header>

  <div>NAME : <span id="typewriter1"></span></div>
  <div>ADDRESS : <span id="typewriter2"></span></div>

</header>

Upvotes: 1

Views: 65

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 371148

You need to

  • not have i or content be global, because then it'll be shared by all calls of typeField
  • have typeField assign to a persistent Promise outside that further calls are chained off of

Consider awaiting a Promise inside a loop, it'll look a lot cleaner than recursion.

const typewriter1 = document.getElementById('typewriter1');
const typewriter2 = document.getElementById('typewriter2');


const name = 'Alim Bolar';
const address = "Some part of the world";
const currentLocation = "Bali, Indonesia";
const profile = "Frontend Development, Backend Development, WordPress Development"

let prom = Promise.resolve();

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
function typeField(textToInsert, element) {
  prom = prom.then(async () => {
    for (const char of textToInsert) {
      element.textContent += char;
      await delay(500);
    }
  });
}

typeField(name, typewriter1);
typeField(address, typewriter2);
<header>
  <div>NAME : <span id="typewriter1"></span></div>
  <div>ADDRESS : <span id="typewriter2"></span></div>
</header>

Upvotes: 2

Related Questions