Мне действительно нравится использовать функции генератора 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>