How do you detect that a script has been loaded * and * executed in a chrome extension?

I tracked the error for several days ... then I realized that the error was me.: /

I used webRequest.onComplete, filtered for scripts. My mistake was that I created the wrong connection between scripts being loaded and executed. They are loaded in a different order than they are executed, and therefore the time of events is not in the order in which I need them. I need to enter between certain scenarios, so I need an event immediately after the file has been executed and the next one earlier.

The only solution I can think of right now is to change the bootable JS before it starts. But it makes my stomach turn. And bfcache will lead to even more chaos, so this is not a great solution.

I would use the HTML5 afterscriptexecute specification, but this is not implemented in Chrome. Is there any other API, possibly an extension API, that I can use?

+4
source share
3 answers

Note. This method no longer works with Chrome 36 . There are no direct alternatives.

Note. The answer below applies only to external scripts, i.e. to those loaded using <script src> .

In Chrome (and Safari), the "beforeload" event fires just before the resource loads. This event allows you to block the resource, so the script is never retrieved. In this case, you can determine if the loaded resource is a script, and check if you want to perform some action

This event can be used to emulate beforescriptexecute / afterscriptexecute :

 document.addEventListener('beforeload', function(event) { var target = event.target; if (target.nodeName.toUpperCase() !== 'SCRIPT') return; var dispatchEvent = function(name, bubbles, cancelable) { var evt = new CustomEvent(name, { bubbles: bubbles, cancelable: cancelable }); target.dispatchEvent(evt); if (evt.defaultPrevented) { event.preventDefault(); } }; var onload = function() { cleanup(); dispatchEvent('afterscriptexecute', true, false); }; var cleanup = function() { target.removeEventListener('load', onload, true); target.removeEventListener('error', cleanup, true); } target.addEventListener('error', cleanup, true); target.addEventListener('load', onload, true); dispatchEvent('beforescriptexecute', true, true); }, true); 

Sending time is not 100% identical to the original, but this is sufficient for most cases. This is a temporary line for (non-emulated) events:

 beforeload Before the network request is started beforescriptexecute Before a script executes afterscriptexecute After a script executes onload After the script has executed 

Here is an easy way to see that events are working as expected:

 window.addEventListener('afterscriptexecute', function() { alert(window.x); }); document.head.appendChild(document.createElement('script')).src = 'data:,x=1'; document.head.appendChild(document.createElement('script')).src = 'data:,x=2'; 

Demo can be seen live on http://jsfiddle.net/sDaZt/

+7
source

I am not familiar with Chrome extensions (only javascript browser), but I think that you, unfortunately, will have to edit the loaded JS so that it calls the function of your choice when it is executed, if you want to make it cute. This is what Google does to asynchronously load its Javascript file into Maps:

 function loadScript() { var script = document.createElement("script"); script.type = "text/javascript"; script.src = "http://maps.googleapis.com/maps/api/js?sensor=false&callback=executed"; document.body.appendChild(script); } function executed() { /* Google maps has finished loading, do awesome things ! */ } 

If you really do not want to edit the loaded JS files, you can regularly check setInterval (or a recursive function with setTimeout ) if some functions or variables are initialized.

0
source

Have you tried loading the script using Modernizr.js?

I had a similar problem when the script load time caused a conflict. I used Modernizr.js, which by default includes the yepnope.js library. Below is an example of some of the scripts that I downloaded conditionally. You can include a test suggestion or simply download them in the order you prefer, with the guarantee that they will be downloaded and executed in the order you want due to the callback.

Here is an example with a conditional sentence:

 Modernizr.load({ test: false, //Or whatever else you'd like. Can be conditional, or not so conditional yep: { 'script1': 'MyJavascriptLibrary1.js' }, nope: { 'script2': 'MyJavascriptLibrary2.js', 'script3': 'MyJavascriptLibrary3.js' }, callback: { 'script1': function (url, result, key) { console.log('MyJavascriptLibrary1.js loaded'); //will not load in this example }, 'script2': function (url, result, key) { console.log('MyJavascriptLibrary2.js loaded first'); }, 'script3': function (url, result, key) { console.log('MyJavascriptLibrary3.js loaded second'); } } }); 

If false, MyJavascriptLibrary2.js and MyJavascriptLibrary3.js will load in the appropriate order, regardless of which elements affect how they behave normally (file size, connection speed, etc.). In these callbacks, you can also run additional javascript in the order in which you want to do this. Example:

 'script2': function (url, result, key) { alert('anything in here will fire before MyJavascriptLibrary3.js executes'); }, 

Please note that this can be done without Modernizr.load ({...

but using just yepnope ({...

For more documentation, visit the yepnope.js API

0
source

Source: https://habr.com/ru/post/1497879/


All Articles