Search code examples
javascriptconcurrencyconcurrentmodification

How to stop the execution of a function on click


I have this typewriter effect, I also have a website in 3 languages. When changing the language, I want the script to be re-executed with the new language. For this, I added an onclick event. Everything works, but there is a bug, if we change the language during the execution of the script, the new one will be executed on top of the old one. So, how, in my case, can I stop the old script and execute the new one?

I tried to use return as posted in other answers, tried to use clearTimeout but still doesn't work.

The snippet does not work. I am using localStorage and here it looks like it is locked.

UPD. The snippet is already working.

var isTag, text, langText, i = 0;
  langText = "Hi!<br>Text,<br>Text ";
(function e() {
  if ((text = langText.slice(0, ++i)) !== langText) {
    document.querySelector(".index-title-main h1").innerHTML = text;
    var t = text.slice(-1);
    if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
    setTimeout(e, 100);
  }
}());
document.querySelector('.en').onclick = function() {
  var isTag, text, langText, i = 0;
    langText = "Hi!<br>Text,<br>Text ";
  (function e() {
    if ((text = langText.slice(0, ++i)) !== langText) {
      document.querySelector(".index-title-main h1").innerHTML = text;
      var t = text.slice(-1);
      if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
      setTimeout(e, 100);
    }
  }());
};
document.querySelector('.de').onclick = function() {
  var isTag, text, langText, i = 0;
    langText = "Hallo!<br>Text,<br>Text ";
  (function e() {
    if ((text = langText.slice(0, ++i)) !== langText) {
      document.querySelector(".index-title-main h1").innerHTML = text;
      var t = text.slice(-1);
      if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
      setTimeout(e, 100);
    }
  }());
};
document.querySelector('.ru').onclick = function() {
  var isTag, text, langText, i = 0;
    langText = "Привет!<br>Текст,<br>Текст ";
  (function e() {
    if ((text = langText.slice(0, ++i)) !== langText) {
      document.querySelector(".index-title-main h1").innerHTML = text;
      var t = text.slice(-1);
      if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
      setTimeout(e, 100);
    }
  }());
};
.lang{
  display: flex;
}
.lang a{
  color: #000;
  width: 100px;
  display: block;
  transition: .5s;
  font-weight: bold;
  text-align: center;
  text-decoration: none;
  border: 1px solid #000;
}
.lang a:not(:last-child){
  margin-right: 10px;
}
.lang a:hover{
  color: #fff;
  transition: .5s;
  background-color: #000;
}
.index-title-main{
  padding-left: 50px;
}
<div class="lang">
  <a class="en" href="#">English</a>
  <a class="de" href="#">Deutsche</a>
  <a class="ru" href="#">Русский</a>
</div>
<div class="index-title-main">
  <h1></h1>
</div>


Solution

  • I have refactored your code and moved the common function outside the click event handler.

    We need to clear the interval at the start of the function as we can be sure that as the execution has reached here we no longer need any previous running instance of other language click handlers.

    var langText, i = 0, timeout;
    
    langText = "Hi!<br>Text,<br>Text ";
    
    function animateText() {
      var isTag, text;
      timeout && clearTimeout(timeout);
      if ((text = langText.slice(0, ++i)) !== langText) {
        document.querySelector(".index-title-main h1").innerHTML = text;
        var t = text.slice(-1);
        if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return animateText();
        timeout = setTimeout(animateText, 100);
      }
    };
    
    animateText();
    
    document.querySelector('.en').onclick = function() {
      i = 0, langText = "Hi!<br>Text,<br>Text ";
      animateText();
    };
    
    document.querySelector('.de').onclick = function() {
      i = 0, langText = "Hallo!<br>Text,<br>Text ";
      animateText();
    };
    
    document.querySelector('.ru').onclick = function() {
      i = 0, langText = "Привет!<br>Текст,<br>Текст ";
      animateText();
    };
    .lang{
      display: flex;
    }
    .lang a{
      color: #000;
      width: 100px;
      display: block;
      transition: .5s;
      font-weight: bold;
      text-align: center;
      text-decoration: none;
      border: 1px solid #000;
    }
    .lang a:not(:last-child){
      margin-right: 10px;
    }
    .lang a:hover{
      color: #fff;
      transition: .5s;
      background-color: #000;
    }
    .index-title-main{
      padding-left: 50px;
    }
    <div class="lang">
      <a class="en" href="#">English</a>
      <a class="de" href="#">Deutsche</a>
      <a class="ru" href="#">Русский</a>
    </div>
    <div class="index-title-main">
      <h1></h1>
    </div>