5

I´m having troubles with AJAX navigation, the problem is that the javascript files loaded remains in the browser after the new content is loaded even they aren't in the DOM anymore, and they appears as VM files in the browser console and execute the code inside it. I don't want that happen because the javascript file it supposed to be replaced when the new content comes via AJAX.

My DOM structure is like this:

<body>
    <header></header>

    <main id="contentToBeReplaced">

        <p>New content with its own js</p>
        <script>
            var script = "js/new.js";
            $.getScript(script);
        </script>
    </main>

    <footer></footer>

    <script src="js/main.js"></script>
</body>

Every time a page is loaded with its own javascript file appears a new VM file and keeps all the olders, and thats a problem:
enter image description here

So, whats the problem and how can I fix this? I need to prevent duplicated files and remove the js file when a new its loaded.

Charlie
  • 22,886
  • 11
  • 59
  • 90
SilverSurfer
  • 4,281
  • 6
  • 24
  • 50
  • Take a look https://stackoverflow.com/questions/17367560/chrome-development-tool-vm-file-from-javascript – User863 Jul 05 '19 at 11:30
  • What I normally do is to give a version number to my latest JavaScript files. For example: js/new.js?v=1... So, next time I generate with js/new.js?v=2.. So, you may return whole url for js file with version from code instead of taking var in script and load js file content from code. – Khurram Ishaque Jul 06 '19 at 09:23
  • https://stackoverflow.com/questions/3466989/what-does-appending-v-1-to-css-and-javascript-urls-in-link-and-script-tags-do – Khurram Ishaque Jul 06 '19 at 09:28
  • Can you actually confirm that the old code is being EXECUTED, or is Chrome DevTools just showing you the code in a previous virtual machine instance? If it is the second case, there is not actually an issue, and you just need to either change devtools settings (if there is such a setting), hit the x button, or ignore them. – ecc521 Jul 10 '19 at 01:35
  • @SilverSurfer How did you determine that each of these scripts in VMs are being executed? – Charlie Jul 12 '19 at 03:33

4 Answers4

3

Each unique entry in Javascript global execution context can only represent a single object or a variable. The repeated loading of the same function to the global context will replace the function code again and again.

You should manage the scripts being lazy-loaded in such a way that they represent the same entry in your global context (or the framework you use)

Look at the following sample js codes which are assumed to be lazy loaded at two different times

//script 1

var dynFun = function() {
                console.log('Loaded early');
             {



//script 2
var dynFun = function() {
                console.log('Loaded late');
             {

Now if you load the script one and execute dynFun(), it will log out "Loaded early". Now, at this point, if you load second script and execute dynFun() again, it will log out "Loaded late" .

However, if each of these functions initiate automatic processes like setTimeout, they will continue to function until the page is closed.

In such occasions, your dynamic scripts should first do some clean up first.

var timeTracker;   //This is global

var dynFun = function() {
                  if (timeTracker)
                      clearTimeout(timeTracker)

                   timeTracker = setTimeout(someFn, 1000)   
             {

Remember - you cannot get to decide deallocation of memory in garbage-collected languages like JS. You can only trick the clean up process by manipulating references to the objects.

Charlie
  • 22,886
  • 11
  • 59
  • 90
  • Thanks for the answer, I dont understand your second example about do clean up with `setTimeout`. – SilverSurfer Jul 12 '19 at 07:37
  • @SilverSurfer Imagine that a function from your first load do setTimeout to carry out a specific task. Now this task is running periodically. Eventually your second load has the same function which carries out the task slightly different way. To prevent two almost similar tasks from running, you will have to cancel the timeout installed by the function from the first load. – Charlie Jul 12 '19 at 07:40
  • 1
    I have found the problem I was facing, however I give you upvote for your answer. Thanks anyway. – SilverSurfer Jul 12 '19 at 08:31
  • //your dynamic scripts should first do some clean up first. – Charlie Jul 12 '19 at 11:35
1

After many research I was able to solve the problem. As far I know there is no absolutely way to "unload" javascript files without refresh the page, or clean the cache of memory browser programmatically.
Since most of my code inside these dynamic javascript files are related to events functions, I was binding events to the document instead of each element with this syntax:

$(document).on("click", "#myElement", function () {

});

For this reason every time the javascript file was loaded the events were binded over and over, and executed multiple times from the VM files. When you remove an element from the DOM, his binded event it´s also removed, unless is binded to document like mine. So I changed the on() method to bind the event directly to the element:

$("#myElement").on("click", function() {

});

After this change my problem has gone because the portion of html I replace with AJAX removes that elements with its events, without the need of use off() to manually remove the binded events, also main functions that will be executed in multiple pages should be placed in the main js.
However, @CharlieH makes a good point in his answer.

SilverSurfer
  • 4,281
  • 6
  • 24
  • 50
0

Add this at the begining of the "new.js" file to track that file in Chrome Dev Tools:

//# sourceURL=new.js
JC Hernández
  • 777
  • 3
  • 13
0

Add 'use strict'; at the top of you JavaScript file it will enable a stricter mode of parsing JavaScript that prevents accidental globals. if it doesn't help you can read more about "garbage collector" in this article "4 Types of Memory Leaks in JavaScript and How to Get Rid Of Them"

Ram Segev
  • 2,563
  • 2
  • 12
  • 24