JavaScript: Как очистить интервал после указания c продолжительности с выполненным условием - PullRequest
0 голосов
/ 11 апреля 2020

Мне нужно запустить приведенный ниже код и через 10 секунд остановить функцию SetInteraval, но в то же время убедиться, что полное слово выполнено.

Код, который я написал:

var word = "I love JS More than any Programming Language in the world!";
var counter = 0;

var autoTyping = setInterval(function() {
  var h3 = document.getElementById("myh3");
  h3.innerText = word.substring(0, counter);
  counter++;

  if (counter > word.length) {
    counter = 0;

  }

}, 100);


setTimeout(function() {
  clearInterval(autoTyping);
}, 5000);

Итак, мне нужно, чтобы через 5 секунд этот код остановился, и это произошло, но его можно остановить, не убедившись, что полное слово «Переменное слово» было полностью написано в DOM.

Ответы [ 4 ]

2 голосов
/ 11 апреля 2020

Я предполагаю, что вы хотите напечатать переменную word для элемента h3 для каждой буквы и остановить ее через 5 с, а переменная была введена полностью.

Вот мое решение с рекурсивным подходом:

[ОБНОВЛЕНИЕ]

  • Добавлен ввод l oop с ограничителем времени ожидания

// word to type
var _word = "I love JS More than any Programming Language in the world!"

// target element's id
var _target = 'myh3'

// time to fully-typed the word
var _time = 5000 // ms

// speed is depend on _time and _word's length
var _speed = _time/_word.length

// your auto-typing stopper 
var _timeout = 10000 // ms

// auto-typing function
function autoType (word, target, speed, timeout) {
  var element = document.getElementById(target)
  var counter = 0
  var stopped = false
  
  function typing(){
    if(counter < word.length){
      element.innerHTML += word[counter]
      counter++
      
      setTimeout(function(){
        // recursive call
        typing()
      }, speed)
    }else{
      // check if you want it to stop
      if(stopped === false){
        // ok. you don't want it to stop now. reset counter
        counter = 0
         
        // reset the element if you want it too
        element.innerHTML = ''
        
        // start it again
        typing()
      }else{
        // console.log('auto-typing is done')
      }
    }
  }
  
  // timeout is required. you dont want a infinite loop, right?
  if(timeout){
    typing()
    
    setTimeout(function(){
      stopped = true
    }, timeout)
  }
}

// execute it
autoType(_word, _target, _speed, _timeout)
body {background: white}
<h3 id="myh3"></h3>
0 голосов
/ 11 апреля 2020

Мне действительно нравится использовать функции генератора ES6, когда дело доходит до интервалов. Они делают код намного чище.

Вот пример многократно используемой функции typewriter, которая принимает элемент, слово и интервал; и возвращает stop функцию:

function typewriter(element, word, interval){
  let stopped = false
  const iterator = (function*() {
    //This try..finally is not necessary, but ensures that typewriter stops if an error occurs
    try{
      while(!stopped){
        for(let i=0; i<word.length; i++){
          element.innerText = word.substring(0, i);
          yield
        }
      }
    }finally{
      clearTimeout(autoTyping)
    }
  })()
  const autoTyping = setInterval(() => iterator.next(), interval);
  iterator.next()

  return function stop(){
    stopped = true
  }
}

const word = "I love JS More than any Programming Language in the world!";
const h3 = document.getElementById("myh3");

const stop1 = typewriter(h3, word, 100)

setTimeout(stop1, 10000)


const secondh3 = document.getElementById("my2ndh3");
const stop2 = typewriter(secondh3, word, 100)
//Even if stopped immediately, it types the full sentence
stop2()
<h3 id="myh3"></h3>
<h3 id="my2ndh3"></h3>

Чтобы возвращать результаты, вы даже можете обещать эту функцию, которая имеет преимущество в наличии канала исключения для асинхронных ошибок:

function typewriter(element, word, interval){
  let stopped = false
  const promise = new Promise((resolve, reject) => {
    const iterator = (function*() {
      try{
        while(!stopped){
          for(let i=0; i<word.length; i++){
            element.innerText = word.substring(0, i);
            yield
          }
        }
        resolve()
      }catch(e){
        reject(e)
      }finally{
        clearTimeout(autoTyping)
      }
    })()
    const autoTyping = setInterval(() => iterator.next(), interval);
    iterator.next()
  })
  promise.stop = function stop(){
    stopped = true
  }
  
  return promise
}

const word = "I love JS More than any Programming Language in the world!";
const h3 = document.getElementById("myh3");

const promise1 = typewriter(h3, word, 100)
promise1.then(() => console.log('1st example done'))
setTimeout(promise1.stop, 10000)

typewriter(null, word, 100) //Cause error with null element
  .catch(e => console.error('2nd example failed:', e.stack))
<h3 id="myh3"></h3>
0 голосов
/ 11 апреля 2020

вы можете просто использовать clearinterval в вашем операторе if, без необходимости иметь функцию setTimeout:

var word = "I love JS More than any Programming Language in the world!";
var counter = 0;
  var h3 = document.getElementById("myh3");
  
var autoTyping = setInterval(function() {
  h3.innerText = word.substring(0, counter);
  counter++;

  if (counter > word.length) {
    counter = 0;
    //clearInterval(autoTyping);
  }

}, 100);

setTimeout(function() {
  if(h3.innerHTML !== word) {
    h3.innerHTML = word;
  }
  clearInterval(autoTyping);
}, 10000);
<div id="myh3">

</div>
0 голосов
/ 11 апреля 2020

Ну, ты почти там. В обратном вызове setInterval добавьте строку, в которой вы очищаете интервал при достижении длины слова.

В обратном вызове setTimeout сначала проверьте, равно ли значение innerText вашего элемента слову. Таким образом, вы можете увидеть, было ли распечатано полное предложение, и остановиться, только если это так. В противном случае setInterval просто продолжит работать, пока не будет достигнута длина слова.

var h3 = document.getElementById("myh3");
var word = "I love JS More than any Programming Language in the world!";
var counter = 0;

var autoTyping = setInterval(function() {
  h3.innerText = word.substring(0, counter);
  counter++;

  if (counter >= word.length) {
    clearInterval(autoTyping);
    counter = 0;
  }

}, 100);

setTimeout(function() {
  if (h3.innerText === word) {
    clearInterval(autoTyping);
  }
}, 5000);
...