Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

164
Views
Iniciar <script> recién insertado después de una llamada AJAX y detener <script> eliminado después de otra llamada AJAX

Estoy haciendo una biblioteca de juguetes en la que el usuario puede modificar el DOM con AJAX, básicamente alrededor de:

 fetch("/newpage").then(r => r.text()).then(html => { var tmp = document.createElement('html'); tmp.innerHTML = html; document.querySelector("#container").outerHTML = tmp.querySelector("#container").outerHTML; // insert in the DOM

El usuario de la biblioteca puede decidir tener bloques <script> en el HTML insertado <div> , así que después de la inserción hago lo siguiente:

 for (const scr of document.querySelectorAll("#container script")) eval(scr.innerHTML);

como se explica en Ejecutar <script> inyectado por innerHTML después de la llamada AJAX .

Esto funciona bien. Pero luego, si se realiza otra llamada AJAX y #container se reemplaza nuevamente por otra cosa, y se elimina el <script> , debemos poder detener todos los scripts en ejecución que se originaron desde el <script> dentro #container . ¿Como hacer esto?

Ejemplo:

  • después de la llamada AJAX #1, #container contiene un <script> con código que se ejecuta periódicamente ( setInterval , etc.). Ahora se está ejecutando gracias a eval (ver arriba)

  • después de la llamada AJAX #2, #container se reemplaza por otra cosa, y este <script> ya no está aquí . Pero la tarea setInterval todavía se está ejecutando... ¿Cómo eliminar esto automáticamente cuando <script> desaparece después de la llamada AJAX #2?

Ideas: ¿podríamos asociar el valor de retorno de eval(..) a una variable, para que podamos realizar un seguimiento de esto y eliminar su ejecución más tarde?
O al insertar <script> con element.outerHTML = ... , ¿deberíamos agregar un identificador (id o clase) al <script> , para que luego podamos tomar medidas sobre el código que lanzó este bloque de script?

Nota: tampoco ¿Es posible detener la ejecución de JavaScript? ni ¿Cómo terminar el script en JavaScript? ni ejecutar <script> inyectado por innerHTML después de la llamada AJAX para resolver esta pregunta.

about 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Puede envolver el setTimeout antes de eval() el script. Cuando elimine el script, puede cancelar el registro de las tareas.

 function mockInternal() { const setTimeout = window.setTimeout; const setInterval = window.setInterval; // window.setImmediate // window.addEventListener const setTimeoutHandlers = []; const setIntervalHandlers = []; window.setTimeout = function mock_setTimeout(callback, delay) { const h = setTimeout(callback, delay); setTimeoutHandlers.push(h); return h; } window.setInterval = function mock_setInterval(callback, delay) { const h = setInterval(callback, delay); setIntervalHandlers.push(h); return h; } return function clearMockInternal() { window.setTimeout = setTimeout; window.setInterval = setInterval; setTimeoutHandlers.forEach(h => clearTimeout(h)); setIntervalHandlers.forEach(h => clearInterval(h)); } } const clearMockInternal = mockInternal(); eval(`setInterval(() => console.log(new Date()), 1000);`); setTimeout(() => { clearMockInternal(); console.log("should not log Date from now"); }, 6000);

about 4 years ago · Santiago Trujillo Report

0

Esta respuesta solo responde a su única pregunta (por intervalo), pero solo quiero compartirla. Puede devolver valores de su evaluación y usarlos para más adelante. Por ejemplo:

índice.html

 <html> <head> </head> <body> <button type="button" onclick="run1()">Run first method</button> <button type="button" onclick="run2()">Run second method</button> <div id="container"> </div> <script> var pro1, pro2; function run1() { if (pro2 != undefined && pro2 != null) { clearInterval(pro2); } fetch("page1.html").then(r => r.text()).then(html => { var tmp = document.createElement('html'); tmp.innerHTML = html; document.querySelector("#container").outerHTML = tmp.querySelector("#container").outerHTML; for (const scr of document.querySelectorAll("#container script")) { pro1 = eval(scr.innerHTML); } }); } function run2() { if (pro1 != undefined && pro1 != null) { clearInterval(pro1); } fetch("page2.html").then(r => r.text()).then(html => { var tmp = document.createElement('html'); tmp.innerHTML = html; document.querySelector("#container").outerHTML = tmp.querySelector("#container").outerHTML; for (const scr of document.querySelectorAll("#container script")) { var data = eval(scr.innerHTML); pro2 = data; } }); } </script> </body> </html>

pagina1.html

 <html> <head> </head> <body> <div id="container"> <script> test(); function test() { var i = 0; const interval = setInterval(function () { console.log(i); i++; }, 1000); return interval; }; </script> </div> </body> </html>

pagina2.html

 <html> <head> </head> <body> <div id="container"> <script> test(); function test() { var i = 9999; const interval = setInterval(function () { console.log(i); i--; }, 1000); return interval; }; </script> </div> </body> </html>

Cada vez que haga clic en un botón, se detendrá otro intervalo

Captura de pantalla para la muestra:

Muestra

Espero que esto ayude.

about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!