vlatkozelka vlatkozelka - 6 months ago 37
Javascript Question

How to stop JavaScript execution when Ajax loads new content?

In the website I am working on, the content is loaded with Ajax, along with any JavaScript included. I am doing this because all the pages are of the same layout, but only the content is the different.

The problem is when a "content" has JavaScript in it, I was afraid the script will continue executing even after new content has been loaded. So I made this test to make sure.

First a main page that will load 2 other pages :

<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>


And then the 2 pages with JavaScript content, basically just spamming the console with "I am page x" every second.

Page 1:

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



<script type="text/javascript">

setInterval(function(){

console.log("I am page 1");

},1000);
</script>

</div>


Page 2:

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



<script type="text/javascript">

setInterval(function(){

console.log("I am page 2");

},1000);
</script>

</div>


The Ajax loads fine, I can see the
h1
changing from
Page 1
to
Page 2
. But in the console, I can see that the first script is still spamming even after the content has been removed.

Is there a way to prevent such behavior? Preferably while keeping each script in it's proper place, and not by moving all scripts to the "main page" .

EDIT: To avoid confusion,
setInterval()
is not the main problem, it's merely an example. I'm asking how do you usually deal with such a problem with Ajax and JavaScript

Answer

Even though the 1st <script> block has been replaced, you see the console logs because of the way javascript works.

Your anonymous function

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

will live on and keep executing till you call clearInterval or move away from this page.

This is also the case when you add a click handlers eg $('#some_button').on("click",function(evt){/*do something*/});

Even if you have a variable declared, like <script>var x='data1';</script> and then you delete the enclosing <script> tag, the variable x will continue to exist.

In both cases, the references to the functions and variables are stored somewhere. References to the setInterval, and click handler function are held by the event handlers. A reference to any var and function you declare is held in the window object (unless you use a closure).

In your newly loaded script, you could re-assign stuff: the behavior of a function will be the last loaded behavior. Any calls made to that function will execute the new instructions because they too have now been assigned to the window object(scope).


In summary,

  1. You will need to clear interval
  2. The functions and vars you declare will exist till you change them

Re:Question in comment

oh, so If I declare a new behavior for a function, it wouldn't give me an error like it would with static programming languages. It 2ould save me a lot of work if I can keep the namings the same. I guess all I need to do is clearInterval, and keep whatever functions as they are.

Right but rather than draw a parallel to other programming languages, try and see these as instructions that are interpreted immediately when you inject the script tag into the DOM. So, what you are doing is actually just re-assigning the properties of the window object. To understand this better, open the developer console on chrome and run these in order:

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

This should help you understand how the JavaScript engine is treating your code.