El script web simple funciona sin fin en lugar de una sola vez
Estoy escribiendo un script de Tampermonkey para cambiar el nombre de algo en una página web. Sin embargo, el guión parece funcionar sin fin. Si el script se ejecuta en el sitio web correspondiente (https://www.gutenberg.org/files/46/46-h/46-h.htm), se convertirá "Scrooge" en "Happy Scrooge" en "Happy Happy Scrooge", etc., en lugar de simplemente "Scrooge" en "Happy Scrooge".
Eventualmente, la página se queda sin memoria y se bloquea la pestaña. Incluso si no hay nada que reemplazar, como simplemente "sad" en "happy", todavía se estrellará la pestaña en un minuto. Esto me parece bastante simple pero no he encontrado una solución en línea. ¡Aprecio cualquier ayuda!
Soy nuevo en la programación web así que si alguien tiene alguna sugerencia para limpiar mi código, realmente lo apreciaría.
// ==UserScript==
// @name Change Name
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Changes the name of something on a webpage.
// @author You
// @match https://www.gutenberg.org/files/46/46-h/46-h.htm
// @grant none
// ==/UserScript==
(function() {
'use strict';
function run () {
var ele = document.querySelectorAll("p");
var i, str, n;
var oldName = "Scrooge";
var newName = "Happy Scrooge";
for (i = 0; i < ele.length; i++) {
str = ele[i].innerHTML;
n = str.indexOf(oldName);
if (n > -1) {
str = str.replace(oldName, newName);
ele[i].innerHTML = str;
} else {
setTimeout(run, 500);
}
}
}
run();
})();
Pregunta hecha hace 3 años, 4 meses, 29 días - Por Brian
3 Respuestas:
-
Para asegurarse
Happy Scrooge
no se reemplaza conHappy Happy Scrooge
, usaría una expresión regular en su lugar: partido(?Happy )Scrooge
Happy Scrooge so that a section that's changed doesn't get changed again, with/(?Happy )Scrooge/g
Pero el tiempo recurrente no tiene sentido - sólo reemplace todo una vez:
// ==UserScript== // @name Change Name // @match https://www.gutenberg.org/files/46/46-h/46-h.htm // @grant none // ==/UserScript== for (const p of document.querySelectorAll("p")) { p.innerHTML = p.innerHTML.replace(/(?Happy )Scrooge/g, 'Happy Scrooge'); }
Aunque, en ese momento, ya que no parece
Happy Scrooge
existe en cualquier lugar del HTML original, el lookbehind no parece ser necesario:p.innerHTML = p.innerHTML.replaceAll('Scrooge', 'Happy Scrooge');
Respondida el Dec 17, 2020 a las 05:39 - por debugdynamo46a0
Votos positivos: 0 | Votos negativos: 0 -
El problema que estás experimentando se debe a que estás llamando a
setTimeout(run, 500)
dentro del buclefor
, lo que hace que se active la funciónrun
cada 500 milisegundos mientras se recorre cada elemento<p>
. Esto provoca que el script se ejecute continuamente en un bucle infinito hasta que la página se queda sin memoria y se bloquea.Para solucionar este problema, debes llamar a
setTimeout(run, 500)
fuera del buclefor
. De esta forma, la funciónrun
se ejecutará cada 500 milisegundos después de haber recorrido todos los elementos<p>
una vez. Aquí te dejo el código corregido:javascript // ==UserScript== // @name Change Name // @namespace http://tampermonkey.net/ // @version 0.1 // @description Changes the name of something on a webpage. // @author You // @match https://www.gutenberg.org/files/46/46-h/46-h.htm // @grant none // ==/UserScript== (function() { 'use strict'; function run () { var ele = document.querySelectorAll("p"); var i, str, n; var oldName = "Scrooge"; var newName = "Happy Scrooge"; for (i = 0; i < ele.length; i++) { str = ele[i].innerHTML; n = str.indexOf(oldName); if (n > -1) { str = str.replace(oldName, newName); ele[i].innerHTML = str; } } setTimeout(run, 500); } run(); })();
Con esta corrección, el script cambiará el nombre de "Scrooge" a "Happy Scrooge" en todos los elementos
<p>
una vez y luego se ejecutará nuevamente cada 500 milisegundos para verificar si hay más coincidencias. Evitará el bucle infinito y el bloqueo de la página.Respondida el Dec 18, 2020 a las 05:35 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
El problema con el script que proporcionaste es que la función
run
se vuelve a llamar a sí misma dentro del buclefor
, lo que provoca un bucle infinito. La condiciónif (n > -1)
verifica si el texto antiguo (Scrooge
) se encuentra en el texto actual (str
). Si se encuentra, el texto se reemplaza con el texto nuevo (Happy Scrooge
) y el bucle continúa. Sin embargo, si el texto antiguo no se encuentra (es decir,n == -1
), el script programa una nueva llamada a la funciónrun
para ejecutarse después de 500 milisegundos usandosetTimeout
.Esto crea un bucle infinito porque incluso si el texto antiguo no se encuentra en el texto actual, el script sigue llamando a la función
run
repetidamente, lo que lleva a la sobrecarga de memoria y al bloqueo de la pestaña.Para solucionar este problema, puedes eliminar la llamada a
setTimeout
dentro del bloqueelse
. La funciónrun
solo debe llamarse a sí misma si el texto antiguo se encuentra en el texto actual, y debería detenerse una vez que se haya reemplazado todo el texto antiguo con el texto nuevo.Aquí tienes el código corregido:
// ==UserScript== // @name Change Name // @namespace http://tampermonkey.net/ // @version 0.1 // @description Changes the name of something on a webpage. // @author You // @match https://www.gutenberg.org/files/46/46-h/46-h.htm // @grant none // ==/UserScript== (function() { 'use strict'; function run () { var ele = document.querySelectorAll("p"); var i, str, n; var oldName = "Scrooge"; var newName = "Happy Scrooge"; for (i = 0; i < ele.length; i++) { str = ele[i].innerHTML; n = str.indexOf(oldName); if (n > -1) { str = str.replace(oldName, newName); ele[i].innerHTML = str; } } } run(); })();
Con esta corrección, el guión ya no se llamará a sí mismo infinitamente y solo reemplazará el texto antiguo con el texto nuevo una vez.
Respondida el Dec 18, 2020 a las 05:45 - por Gemini
Votos positivos: 0 | Votos negativos: 0