Я создал специальную функцию для репликации функции setInterval. Вот что я пытаюсь сделать:
<html>
<head>
<script id='scpt_a'>
//custom setInterval function
function interval(func,ti){
try{
func.call(null);
}
catch(err){
throw new Error(err.toString());
}
setTimeout(()=>{interval(func,ti); },ti);
}
//custom setinterval function end
$('#start).click(()=>{
$('body').append("<script id='scpt_b'>interval(()=>
{console.info('hello');},10000);</script>");
});
$('#stop).click(()=>{
$('#scpt_a').remove();
$('#scpt_b').remove();
});
</script>
</head>
<body>
<button id='start'>start</button>
<button id='stop'>stop</button>
</body>
</html>
всякий раз, когда я запускаю этот код, он работает нормально, т.е. когда я нажимаю на кнопка Пуск, он добавляет код, поэтому код выполняет его и продолжает печатать Привет. Теперь, когда я нажимаю кнопка остановки, это удаляет, добавленный скрипт, а также начальный (не добавленный) скрипт. Итак, поскольку скрипта нет, он должен прекратить выполнение, но этого не происходит.
Я использовал инструменты разработчика Chrome, где я увидел, что после нажатия кнопка остановкине было сценария (после добавления он был там) в документе HTML, но Привет все еще печатал на консоли.
пожалуйста, помогите мне разобраться, почему так происходит и как это исправить.
Когда вы добавляете скрипт на свою страницу, он анализируется браузером. Когда вы позже удалите тег сценария, это не имеет значения, сценарий уже был проанализирован, обработан и находится в памяти браузера. Таким образом, ваша функция interval
будет продолжать работать, несмотря на то, что вы удалили тег скрипта со страницы.
Вот иллюстрация этого факта. Я добавил ссылку на jQuery, см. Первое предупреждение, затем удаляю его, а после этого удаляю тег сценария jQuery, и вы можете видеть, что я все еще могу использовать функцию jQuery $
:
<script id = "s1" src = "https://code.jquery.com/jquery-3.3.1.js"></script>
<script>
alert($);
$("#s1").remove();
alert($);
</script>
Как уже указывалось в ответе xxxmatko, удаление элемента скрипта из DOM не останавливает его запуск, если он уже был проанализирован.
Вам нужно придумать другое решение, чтобы отменить выполнение вашего интервала. Возможно, самый простой способ - использовать вместо нее стандартную функцию setInterval
. Это можно сделать следующим образом:
// Start the interval:
let intervalID = setInterval(function() { /* your code */}, 10000);
// Stop the interval:
clearInterval(intervalID);
Однако, если вы настаиваете на настраиваемой функции интервала, такой как та, что в вашем примере, вы могли бы реализовать некоторые функции, которые позволят вам отменить интервал позже аналогичным образом. Например, вы можете проверить условие в функции интервала:
function interval(func,ti){
/* your code */
if ( /* some condition */ )
setTimeout(()=>{interval(func,ti); },ti);
}
И когда щелкают $('#start')
или $('#stop')
, это условие устанавливается в истинное или ложное соответственно.
Более того, оба этих решения позволяют избежать еще одной проблемы в вашем коде: если пользователь дважды щелкнет $('#start')
, вы получите два элемента скрипта (с одинаковым идентификатором!) В DOM.