Overwriting of the document.write to delay a script's execution - javascript

I'm try for delaying the execution of this ad script:
<script type="text/javascript">
var _pop = _pop || [];
_pop.push(['siteId', 809347]);
_pop.push(['minBid', 0.000000]);
_pop.push(['popundersPerIP', 0]);
_pop.push(['delayBetween', 0]);
_pop.push(['default', false]);
_pop.push(['defaultPerDay', 0]);
_pop.push(['topmostLayer', false]);
(function() {
var pa = document.createElement('script'); pa.type = 'text/javascript'; pa.async = true;
var s = document.getElementsByTagName('script')[0];
pa.src = '//URL/pop.js';
pa.onerror = function() {
var sa = document.createElement('script'); sa.type = 'text/javascript'; sa.async = true;
sa.src = '//URL/pop.js';
s.parentNode.insertBefore(sa, s);
};
s.parentNode.insertBefore(pa, s);
})();
</script>
For do this I have apply setTimeout in this way:
setTimeout (function() {
(function() {
var pa = document.createElement('script'); pa.type = 'text/javascript'; pa.async = true;
var s = document.getElementsByTagName('script')[0];
pa.src = '//c1.popads.net/pop.js';
pa.onerror = function() {
var sa = document.createElement('script'); sa.type = 'text/javascript'; sa.async = true;
sa.src = '//c2.popads.net/pop.js';
document.head.appendChild(sa, s);
};
document.head.appendChild(pa, s);
})(); }, 2300);
</script>
And changed s.parentNode.insertBefore with document.head.appendChild
The script start but I not see delay.
I have read "If the target script expects to be run synchronously and uses document.write you're out of luck. Unless, you want to do some messy hacks involving overwriting of the native document.write function.
I need for overwriting document.write?

You can delay the execution of any script by many methods. Simple ones:
Place your script tags just before the end of your page body, so that they are loaded after the browser has parsed the rest of the page. Therefore the browser is able to render the page before your script executes.
Add the defer="defer" attribute to your script tag (if it loads an external file). Execution is delayed at the end of page parsing.
Use a setTimeout wrapped around the code to be delayed, as you tried. Make sure the setTimeout itself is wrapped to be executed on DOM ready event, otherwise it will start the counter at execution, before the rest of the page is rendered, and you may see no effect if that rendering is slow.
Load a script asynchronously after a given timeout (but refer to point 3 about DOM ready event). In your case, why not putting the ad loader code in an external file (so you do not even have to modify it!), and load it later (using a similar script loading method)? Yes, that would be loading a loader…
Side notes:
Use of someScriptElement.parentNode.insertBefore is considered a better practice than document.head.appendChild, as a document may not have a head tag.
The sentence you quoted means that any script that relies on document.write forces you to load it synchronously (and therefore document.write should be avoided whenever possible). You may try to emulate the synchronous load by overwriting the document.write function, so that you could nevertheless load the script asynchronously. But in your case, the ad code does not use document.write, and it loads another script asynchronously, so you do not have to bother.

Related

createElement script ,async=false,don't work

createElement script ,async=false,don't work
<script>
let script = document.createElement('script');
script.src = 'a.js';
script.async = false;
document.head.appendChild(script);
console.log(a); // undefined
</script>
a.js is just var a = 123;createElement script is async default,so i use async=false,but it look like don't work
Yes, <script> elements that are not "parser inserted" have their force async flag set to true. Setting the async attribute will set that flag to false, but then, it will be either async per the attribute, or it will only make it appended in the list of scripts that will execute in order as soon as possible instead of in the set of scripts that will execute as soon as possible. This will ensure that if you do load another script that way, they'll load in the order you defined, but they will still be loaded in parallel.
You can however add a load event handler on your <script> to wait until it's properly loaded.
const el = document.createElement("script");
el.src = "https://app.requestly.io/delay/2000/https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js";
el.async = false;
el.onload = (evt) => console.log(typeof jQuery);
document.body.append(el);

Does this Funnelytics code contain a race condition?

I'm looking into tracking scripts that I've come across. Here's one by Funnelytics. At first look it seems like it has a bug:
(function(funnel) {
var insert = document.getElementsByTagName('script')[0],
script = document.createElement('script');
script.addEventListener('load', function() {
window.funnelytics.init(funnel, false);
});
script.src = 'https://cdn.funnelytics.io/track.js';
script.type = 'text/javascript';
script.async = true;
insert.parentNode.insertBefore(script, insert);
})('8889dbc2-6c2f-5ba4-c201-dc8889dbc26c');
Isn't it possible that the function triggered by load will be called before the asynchronous script track.js gets executed? In which case, won't the line window.funnelytics.init fail, since window.funnelytics hasn't been defined yet?
This code does not contain a race condition. Notice that the event listener is attached to the script element, not the window object:
script.AddEventListener('load', function() { // ...
This function will only get called once the script loads and is executed.
Even if the event listener had been attached to the window object, this code would still not contain a race condition. The function would only get called once all the window's subresources get loaded and executed, including any async scripts that are dynamically inserted, as happens here.

How to add new script and wait for it to execute in Javascript

Let's say I've got my-file.js or some CDN file in different server that has
for (var i = 0; i < 1000; i ++) {
//something really long and hard to execute
}
//after this long execution
window.myObj = {
//initialization of some global object that I need
}
(I cannot change my-file.js...)
I want to add my-file.js asynchronously to page, and then, after it is loaded and EXECUTED I want to call some event like:
//when my my-file.js is loaded I finally use window.myObj
window.myObj.somefunc(); //yaaay
Is it possible? (cross browser for IE9+ is important for me, but any not critical)
Note:
In case file I need is on CDN or somewhere on different server - I need to remember about cross-domain policy, so I think loading content of file in ajax is not possible in such case.
Note 2:
http://www.chromestatus.com/features/5711871906676736 there is exacly what I need, but I bet it'll be few years before you can easly use it globally.
var script = document.createElement('script');
script.onload = function(){
// loaded
}
document.head.appendChild(script);
script.src = "path/to/script";
That's about the simplest example. And yes, the entire thing is async, hence it needed the onload handler.
You could also wrap it up in a function:
function getScript(src,callback){
var script = document.createElement('script');
script.onload = callback;
document.head.appendChild(script);
script.src = src;
}
getScript('path/to/js',function(){
//loaded
});
However, thinking out of the box, it sounds like you need dependency management. Use RequireJS. Should fit your needs.
jQuery getScript has a callback you can use to execute events after a file is loaded, or you can use script.onload as in Joseph's example:
http://api.jquery.com/jquery.getscript/
If you want to wait until a certain property is available (ie after some work has finished), you can create an interval and then clear it as soon as the property is found in window, ie:
var waitForObj = setInterval(function(){
if(window.myObj && window.myObj.somefunc){
clearInterval(waitForObj);
//Do some stuff you need this object for
}
}, 100);

why isn't jQuery loading?

When using an importjs() type of function (see below for an example), jQuery doesn't seem to be loading before the code following it.
Here's a sample html file:
<html>
<head></head>
<body>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
function importjs(jsFile) {
var body = document.getElementsByTagName('head').item(0);
var scpt = document.createElement('script');
scpt.src = jsFile;
scpt.type = 'text/javascript';
body.appendChild(scpt);
}
var f1="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js";
//importjs(f1);
var $j=jQuery;
alert("hello stackoverflow!");
</script>
</body>
</html>
With the above code, the alert should successfully fire.
Next, comment out the first script block, i.e. the one explicitly loading jQuery, and uncomment the importjs(f1) line in the second script block. This time, the alert does not fire, at least in firefox and safari.
Now, put in an extra alert before the line "var $j=jQuery". For me, it works in both browsers, regardless of how long or short I wait. A setTimeout would probably also do the trick, but it's also not an ideal way to program something like this.
If javascript is single-threaded, why does the importjs fail? Is it because the new element created by importjs doesn't get 'executed' until the first block finishes, or should the new element be executed as soon as it is created?
There are several problems here:
you have jQuery duplicated, one in the html, one in the js
dynamically added javascript won't be available immediately
if you load scripts this way the dependant code should be in a callback function
function importjs(jsFile, callback) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = jsFile;
script.type = 'text/javascript';
script.onload = script.onreadystatechange = function() {
// execute callback
if (callback) callback();
// prevent memory leak in IE
script.onload = null;
head.removeChild(script);
};
head.appendChild(script);
}
then you should use it as:
importjs("jquery.js", function(){
// all jQuery dependant code
// goes here...
});​
UPDATE
There is a more robust solution for including javascript files which allows you to:
include multiple files that are related
ensure they are executed in order
load them in a non-blocking way (parallel with other resources)
I'm still working on this script, but pretty much works right now. Be sure to check it out.
It combines the advantages of different techniques to give a huge benefit on page load time. Here is a related article: Loading Scripts Without Blocking
The syntax is:
include(['jquery.js','jquery-ui.js'], myjQueryCode); // executed in order

How do I perform a callback on JQuery once it's loaded?

I'm downloading JQuery asynchronously:
function addScript(url) {
var script = document.createElement('script');
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}
addScript('jquery.js');
// non-jquery code ...
// jquery specific code like: $()...
As such - how do I call my JQuery specific code once JQuery is loaded (because since I'm downloading my JavaScript asynch - it's not blocking, which is good, but is trying to execute my JQuery specific code before JQuery has been loaded).
You can host a copy of the jquery file yourself. Then you can add a call to the callback function at the bottom of jquery.js:
/* jquery code goes here ... */
my_onload_callback();
For me this works (tested in FireFox 33.0.3):
if(typeof(jQuery) == "undefined"){
//create onload-callback function
window["__9384nalksdfalkj04320"] = function(){
console.log("jQuery=" + jQuery);
};
//load jQuery asynchronously
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("onload", "__9384nalksdfalkj04320();"); //register onload-callback listener function
script.setAttribute("src", "http://code.jquery.com/jquery-latest.min.js");
document.head.appendChild(script);
}
You can inline LabJs into your page (potentially, every page). On the downside, you're inlining a script over and over. On the upside, LabJs is pretty small - 4k minified - and it lets you handle complex asynchrony load patterns cross-browser with very simple code like:
<script>
// Minified LabJs goes here
</script>
<script>
function init() {
// Your code after jquery loads goes here
}
$LAB
.script('//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js')
.wait(init);
</script>
</body>
I'm not much on standard Javascript, but you may try doing something like this:
var script_object = new addScript('jquery.js');
script_object.onLoad('addScript("my_jquery_related.js")');
Admittedly, that's a mega shot in the dark.
If that doesn't work, maybe pass through your function as a callback variable in your JS loader:
addScript(url, function(){ function_to_call();})
function addScript(url, call_back_function) {
var script = document.createElement('script');
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
call_back_function.call;
}
addScript('jquery.js');
That's all I got :\

Categories

Resources