Paul Braganza
Paul Braganza

Reputation: 151

JavaScript [ memory leak ] : animation using javascript causes memory leak

Problem statement: As a developer, I want to develop a typewriting animation effect that should run on the page as long as the page is alive without causing any performance issues on the page (memory leak).

Issue What I'm facing right now is my code is causing a memory leak which I want to avoid.

enter image description here

This What I have developed so far.

let loopAnimation = true;
let animationTimeout;
let animationBase = 'Develop in ';
let animationPool = ['HTML', 'CSS', 'JavaScript'];
let animationCounter = 0;
let animation = animationBase + animationPool[animationCounter];
let i = 1;

let timeoutReadable = 1750;
let timeoutTyping = 100;
let timeoutDeleting = 70;

let span = document.getElementById('animationtextbox');
let forwarding = false;
let currentWord;

function sleep(ms) {
  return new Promise((resolve) => {
    animationTimeout = setTimeout(() => {
      resolve();
      return null;
    }, ms);
  });
}

textAnimation();

async function textAnimation() {
  while (loopAnimation) {
    currentWord = null;
    currentWord = animationPool[animationCounter];
    if (forwarding) {
      if (i < currentWord.length) {
        // play effect (type word)
        span.innerText =
          animationBase + currentWord.slice(0, i - currentWord.length);
        i++;
        forwarding = true;
        await sleep(timeoutTyping);
      } else {
        span.innerText = animationBase + currentWord;
        i = 1;
        forwarding = false;
        await sleep(timeoutReadable);
      }
    } else {
      if (i <= currentWord.length) {
        // play effect (remove word)
        span.innerText =
          animationBase + animationPool[animationCounter].slice(0, i * -1);
        i++;
        forwarding = false;
        await sleep(timeoutDeleting);
      } else {
        // switch animation word
        i = 1;
        if (animationCounter < animationPool.length - 1) {
          animationCounter++;
        } else {
          animationCounter = 0;
        }
        forwarding = true;
        await sleep(timeoutTyping);
      }
    }
  }
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <span id="animationtextbox"></span>
  </body>
</html>

Upvotes: 1

Views: 556

Answers (2)

user1566268
user1566268

Reputation: 105

actually for a single-page Web App, even using pure CSS code (e.g. "transition: ease 0.2s;"), Chrome will have a memory leak.

so we have no choise to delete all the "transition" in our CSS.

it take a lot of time to find this problem.

Upvotes: 0

Snivio
Snivio

Reputation: 1864

You are not Clearing your timeouts

add

await clearTimeout()

After every timeout you create

replace your function with

async function textAnimation() {
  while (loopAnimation) {
    currentWord = null;
    currentWord = animationPool[animationCounter];
    if (forwarding) {
      if (i < currentWord.length) {
        // play effect (type word)
        span.innerText =
          animationBase + currentWord.slice(0, i - currentWord.length);
        i++;
        forwarding = true;
        await sleep(timeoutTyping);
        await clearTimeout(animationTimeout )
      } else {
        span.innerText = animationBase + currentWord;
        i = 1;
        forwarding = false;
        await sleep(timeoutReadable);
        await clearTimeout(animationTimeout)
      }
    } else {
      if (i <= currentWord.length) {
        // play effect (remove word)
        span.innerText =
          animationBase + animationPool[animationCounter].slice(0, i * -1);
        i++;
        forwarding = false;
        await sleep(timeoutDeleting);
        await clearTimeout(animationTimeout);
      } else {
        // switch animation word
        i = 1;
        if (animationCounter < animationPool.length - 1) {
          animationCounter++;
        } else {
          animationCounter = 0;
        }
        forwarding = true;
        await sleep(timeoutTyping);
        await clearTimeout(animationTimeout);
      }
    }
  }
}

Upvotes: 1

Related Questions