Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I apply a delay to .then promise? [duplicate]

I have the following functions:

async typewrite(what, where){} - simulates somebody inputting text
async typeerase(where){} - similar as typewrite, but simulates somebody pressing backspace typetimer(){} - returns a promise, random interval to simulate typing speed.

Basically, what I want to do is after the typewrite function finishes, I want to erase the text after a small delay. I tried artificially delaying it with a setTimeout, but that does not seem to work.


The following code works as expected

typewrite('Hello world!', target).then(erase => typeerase(target));

let typetimer = (fmin, fmax) => ( 
  new Promise(res => setTimeout(res, Math.floor(Math.random() * (fmax - fmin + 1)) + fmin))
); 

const textarea = document.getElementById('textarea');

async function typewrite(what, where){
  let current_text = '';
  const typespeed_min = 50;
  const typespeed_max = 150;
  
  for (let i = 0; i < what.length; i++){
    await typetimer(typespeed_min, typespeed_max);
    current_text += what.charAt(i);
    where.innerHTML = current_text;
  }
}


async function typeerase(where){
  const erasespeed_min = 30;
  const erasespeed_max = 70;
  let current_text = where.textContent;
  
  while (current_text.length > 0){
    await typetimer(erasespeed_min, erasespeed_max)
    current_text = current_text.substring(0, current_text.length - 1);
    where.innerHTML = current_text;
  }  
}

typewrite('Hello, I am an asynchronous function!', textarea)
  .then(erase => typeerase(textarea));
html {
  font-family: 'Courier New';
  font-weight: bold;
  font-size: 15pt;
}
<p id="textarea"></p>

However, applying artificial setTimeout() delay does not seem to affect it at all.

typewrite('Hello world!', target).then(erase => setTimeout(typeerase(target), 50000));

let typetimer = (fmin, fmax) => ( 
  new Promise(res => setTimeout(res, Math.floor(Math.random() * (fmax - fmin + 1)) + fmin))
); 

const textarea = document.getElementById('textarea');

async function typewrite(what, where){
  let current_text = '';
  const typespeed_min = 50;
  const typespeed_max = 150;
  
  for (let i = 0; i < what.length; i++){
    await typetimer(typespeed_min, typespeed_max);
    current_text += what.charAt(i);
    where.innerHTML = current_text;
  }
}


async function typeerase(where){
  const erasespeed_min = 30;
  const erasespeed_max = 150;
  let current_text = where.textContent;
  
  while (current_text.length > 0){
    await typetimer(erasespeed_min, erasespeed_max)
    current_text = current_text.substring(0, current_text.length - 1);
    where.innerHTML = current_text;
  }  
}

typewrite('Hello, I am an asynchronous function!', textarea)
  .then(erase => setTimeout(typeerase(textarea), 100000000));
html {
  font-family: 'Courier New';
  font-weight: bold;
  font-size: 15pt;
}
<p id="textarea"></p>

It appears I'm almost missing something very basic / fundamental here, but I just can't seem to realise what am I doing wrong here.

like image 679
Samuel Hulla Avatar asked Dec 17 '22 18:12

Samuel Hulla


1 Answers

Short answer: setTimeout doesn't work like that. You should be able to do this instead:

typewrite('Hello world!', target)
    .then(erase => setTimeout(() => typeerase(target), 50000));

Long answer: You should probably use a helper method that wraps setTimeout to produce a desired delay (Noitidart's answer shows an example of this)...

typewrite('Hello world!', target)
    .then(() => delay(50000))
    .then(() => typeerase(target));

... and then use await

await typewrite('Hello world!', target);
await delay(50000);
await typeerase(target);
like image 62
StriplingWarrior Avatar answered Jan 05 '23 17:01

StriplingWarrior