Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
311 views
in Technique[技术] by (71.8m points)

javascript - Stop IE from loading dynamically included script twice

I am including some related content on misc. web pages by adding a <script> tag near the end of the <body> tag, which then loads other javascript files. The flow is a little convoluted, so I’ll try to explain it before asking my question:

  • A browser loads a page with our <script> element near the end of the <body> element
  • The src attribute of the script tag points to a javascript file which (in some cases) injects a second <script> element
  • The src attribute of the injected <script> element points to yet another javascript file, which finally injects some content on the appropriate part of the page.

We are using this two-stage approach to be able to do some basic processing before deciding whether to include the final content, which could take some time to load.

The problem is that IE8 (and maybe older versions) loads the last javascript twice. It appears that the act of setting the src attribute will trigger a load, but so will appending the script tag to the DOM. Is there any way to avoid this?

I have created a bare-bones demo of the problem. If you have some way of tracing the HTTP requests, you will see that IE8 loads js_test2.js twice.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The root difference is that IE executes a script element the first time it is added to a parent element's childNodes, regardless of whether the parent element is actually in the document. Other browsers only execute script when it is added to a node inside the document's tree of childNodes.

jQuery's domManip function (line 524 of jQuery 1.3.2), which is called by append and other similar jQuery methods, tries to be clever and calls evalScript for any <script> elements it finds in the final parsed HTML, to execute the script (by doing AJAX requests if necessary for external scripts). (The actual script elements have been removed from the parsed childNodes to stop them getting executed on insertion into the document, presumably so that scripts are only executed once when content containing them is appended into multiple elements at once.)

However, because the previous clean function, whilst parsing the HTML, appended the script element to a wrapper div, IE will have already executed the script. So you get two executions.

The best thing to do is avoid using domManip functions like append with HTML strings when you're doing anything with scripts.

In fact, forget putting your content in a serialised HTML string and getting jQuery to parse it; just do it the much more reliable plain DOM way:

var s= document.createElement('script');
s.type= 'text/javascript';
s.charset= 'UTF-8';
s.src= 'js_test2.js';
document.getElementById('some_container').appendChild(s);

(To be honest, after viewing the stomach-churning source code of the clean function, I'm having serious doubts about using jQuery's HTML-string-based DOM manipulations for anything at all. It's supposed to fix up browser bugs, but the dumb-regex processing seems to me likely to cause as many problems as it solves.)

Incidentally with this initial call:

document.write(unescape("%3Cscript src='js_test1.js' type='text/javascript'%3E%3C/script%3E"));

You don't need to unescape here; I don't know why so many people do. The sequence </ needs to be avoided in an inline script as it would end the <script> tag, and if you're doing XHTML < and & should be avoided too (or ]]> if you're using a CDATA wrapper), but there's an easier way of doing all that with just JavaScript string literals:

document.write('x3Cscript src="js_test1.js" type="text/javascript">x3C/script>"));

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...