如何在Ajax加载新内容时停止JavaScript执行


How to stop JavaScript execution when Ajax loads new content?

在我正在开发的网站中,内容是用Ajax加载的,以及包含的任何JavaScript。我这样做是因为所有的页面都是相同的布局,但只有内容不同。

问题是,当"内容"中包含JavaScript时,我担心即使加载了新内容,脚本也会继续执行。所以我做了这个测试来确定。

首先是一个将加载2个其他页面的主页:

<script src="scripts/jquery.min.js"></script>
<script>
function loadPage1(){
var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                if (xhttp.readyState == 4 && xhttp.status == 200) {
                    response = xhttp.responseText;                  
                    $("#content").remove();
                    $("#mainContent").append(response);
                }
            };

            xhttp.open("GET", "page1.html", true);
            xhttp.send();

}

function loadPage2(){

var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                if (xhttp.readyState == 4 && xhttp.status == 200) {
                    response = xhttp.responseText;                  
                    $("#content").remove();
                    $("#mainContent").append(response);
                }
            };

            xhttp.open("GET", "page2.html", true);
            xhttp.send();
}

</script>

<button onclick="loadPage1()">Load page 1</button>
<button onclick="loadPage2()">Load page 2</button>
<div id="mainContent">
</div>

然后是两个包含JavaScript内容的页面,基本上只是每秒向控制台发送"我是x页面"。

第1页:

<div id="content">
<h1>Page 1</h1>

<script type="text/javascript">
    setInterval(function(){
console.log("I am page 1");
    },1000);
</script>
</div>

第2页:

<div id="content">
<h1>Page 2</h1>

<script type="text/javascript">
    setInterval(function(){
console.log("I am page 2");
    },1000);
</script>
</div>

Ajax加载良好,我可以看到h1Page 1变为Page 2。但在控制台中,我可以看到,即使内容被删除,第一个脚本仍然在垃圾邮件中。

有没有办法防止这种行为?最好将每个脚本放在适当的位置,而不是将所有脚本移动到"主页"。

EDIT:为了避免混淆,setInterval()不是主要问题,它只是一个例子。我在问您通常如何处理Ajax和JavaScript 的此类问题

尽管第一个<script>块已经被替换,但由于javascript的工作方式,您可以看到控制台日志。

您的匿名功能

function(){
    console.log("I am page 1");
}

将继续执行,直到调用clearInterval或离开此页面。

当您添加点击处理程序时也是如此,例如$('#some_button').on("click",function(evt){/*do something*/});

即使您声明了一个变量,如<script>var x='data1';</script>然后删除封闭的<script>标记,则变量x将继续存在。

在这两种情况下,对函数和变量的引用都存储在某个地方。对setInterval和click处理程序函数的引用由事件处理程序持有。对您声明的任何varfunction的引用都保存在window对象中(除非您使用闭包)。

在新加载的脚本中,您可以重新分配内容:函数的行为将是最后加载的行为。对该函数的任何调用都将执行新指令,因为它们现在也已分配给窗口对象(作用域)。


总之,

  1. 您需要清除间隔
  2. 您声明的函数和变量将一直存在,直到您更改它们

回复:评论中的问题

哦,所以如果我为一个函数声明一个新的行为,它不会像静态编程语言那样给我一个错误。如果我能保持不变的话,这将为我节省很多工作。我想我所需要做的就是clearInterval,并保持任何函数的原样。

是的,但与其与其他编程语言进行比较,不如尝试将这些语言视为在将脚本标记注入DOM时立即解释的指令。因此,您所做的实际上只是重新分配窗口对象的属性。为了更好地理解这一点,请打开chrome上的开发人员控制台,并按以下顺序运行:

window.hasOwnProperty("xy")
var xy=1
window.hasOwnProperty("xy")
window.xy
xy="foo"
typeof window.xy 
typeof window 

这将帮助您了解JavaScript引擎是如何处理代码的。

您删除/替换了内容,而不是脚本,您仍然在同一页上。此外,您只将新数据加载到该页面中,因此您的脚本仍在该页面中运行,除非它明确停止或在页面重新加载时停止。