Estoy tratando de hacer un efecto de máquina de escribir personalizado en mi sitio usando una función javascript. Para agregar un retraso entre la escritura de cada letra, implementé un setTimeout escalonado para cada ejecución del ciclo for, por lo que cada iteración se retrasa 300 ms en comparación con la anterior. Necesito que los caracteres especiales (' ' '<', '>') se escriban como caracteres individuales en lugar de letras individuales, por lo que tengo algunas else if condiciones. Esto produce el efecto deseado cuando se excluye setTimeout . Sin embargo, agregar el retraso da como resultado que se deletreen las letras individuales de este código después de imprimir el carácter completo. ¿Cómo puedo arreglar esto?
function type(fullTxt, current = '') { for (let i = current.length, j = 0; i < fullTxt.length; i++, j++) { setTimeout(function() { if (fullTxt.substring(i, i+6) === ' ') { console.log(fullTxt.substring(0, i+6)); i = i + 5; } else if (fullTxt.substring(i, i+4) === '<') { console.log(fullTxt.substring(0, i+4)); i = i + 3; } else if (fullTxt.substring(i, i+3) === '>') { console.log(fullTxt.substring(0, i+3)); i = i + 2; } else { console.log(fullTxt.substring(0, i+1)); } console.log(j); //included just to ensure j is counting properly console.log(i); //included to check progress of loop console.log(fullTxt.length); //included to check endpoint of for loop }, j * 300); } } type('hello ');Rendimiento esperado:
// h // 0 // 0 // 11 // he // 1 // 1 // 11 // hel // 2 // 2 // 11 // hell // 3 // 3 // 11 // hello // 4 // 4 // 11 // hello // 5 // 10 // 11puedes lograr esto usando la función async
async function type(fullTxt, current = '') { for (let i = current.length, j = 0; i < fullTxt.length; i++, j++) { await waitFor(j*300); if (fullTxt.substring(i, i+6) === ' ') { console.log(fullTxt.substring(0, i+6)); i = i + 5; } else if (fullTxt.substring(i, i+4) === '<') { console.log(fullTxt.substring(0, i+4)); i = i + 3; } else if (fullTxt.substring(i, i+3) === '>') { console.log(fullTxt.substring(0, i+3)); i = i + 2; } else { console.log(fullTxt.substring(0, i+1)); } console.log(j); //included just to ensure j is counting properly console.log(i); //included to check progress of loop console.log(fullTxt.length); //included to check endpoint of for loop } } type('hello '); aquí está la función waitFor
function waitFor(ms){ return new Promise(resolve=> setTimeout(resolve,ms)) }Lo más seguro ahora es usar async/await , llamando a Promise , de esta manera, su bucle en realidad está esperando que se complete el anterior.
Además, esto hace que las cosas sean fáciles de escribir o modificar posteriormente.
Tiempo de espera establecido en 2000 ms para la demostración.
async function type(fullTxt, current = '') { for (let i = current.length, j = 0; i < fullTxt.length; i++, j++) { await wait(2000) // Wait for 2000ms if (fullTxt.substring(i, i+6) === ' ') { console.log(fullTxt.substring(0, i+6)); i = i + 5; } else if (fullTxt.substring(i, i+4) === '<') { console.log(fullTxt.substring(0, i+4)); i = i + 3; } else if (fullTxt.substring(i, i+3) === '>') { console.log(fullTxt.substring(0, i+3)); i = i + 2; } else { console.log(fullTxt.substring(0, i+1)); } console.log(j); //included just to ensure j is counting properly console.log(i); //included to check progress of loop console.log(fullTxt.length); //included to check endpoint of for loop } } // Generic Promise function function wait(delayInMS) { return new Promise((resolve) => setTimeout(resolve, delayInMS)); } type('hello ');Puede colocar setTimeout solo en console.log en lugar de en toda la instrucción if .
function type(fullTxt, current = '') { for (let i = current.length, j = 0; i < fullTxt.length; i++, j++) { if (fullTxt.substring(i, i + 6) === ' ') { setTimeout(function() { console.log(fullTxt.substring(0, i + 6)); }, j * 300); i = i + 5; } else if (fullTxt.substring(i, i + 4) === '<') { setTimeout(function() { console.log(fullTxt.substring(0, i + 4)); }, j * 300); i = i + 3; } else if (fullTxt.substring(i, i + 3) === '>') { setTimeout(function() { console.log(fullTxt.substring(0, i + 3)); }, j * 300); i = i + 2; } else { setTimeout(function() { console.log(fullTxt.substring(0, i + 1)); }, j * 300); } setTimeout(function() { console.log(j); //included just to ensure j is counting properly console.log(i); //included to check progress of loop console.log(fullTxt.length); //included to check endpoint of for loop }, j * 300); } } type('hello ');