Disabling the long-running-script message in Internet Explorer

I have a JavaScript function that contains a for loop that repeats so many times. After calling this function, IE browser displays this message:

Stop executing this script?
A script on this page makes the web browser run slowly. If it continues to work, your computer may stop responding.

How can i fix this? is there anyway i can disable this message from IE?

+47
javascript internet-explorer
Dec 16 '10 at 11:26
source share
4 answers

This message is displayed when Internet Explorer reaches the maximum number of synchronous instructions for a JavaScript fragment. The maximum default value is 5,000,000 instructions; you can increase this number on one machine by editing the registry .

Internet Explorer now monitors the total number of script statements executed and resets the value each time a new script execution is launched, for example, from a timeout or from an event handler, for the current page with the script engine. Internet Explorer displays a long-running script dialog box when this value exceeds a threshold value.

The only way to solve the problem for all users who can view your page is to break the number of iterations that your cycle performs with timers, or reorganize your code so that it does not process so many instructions.

Opening a cycle with timers is relatively simple:

var i=0; (function () { for (; i < 6000000; i++) { /* Normal processing here */ // Every 100,000 iterations, take a break if ( i > 0 && i % 100000 == 0) { // Manually increment `i` because we break i++; // Set a timer for the next iteration window.setTimeout(arguments.callee); break; } } })(); 
+79
Dec 16 '10 at 11:33
source share

The script dialog is not responding when the javascript stream is too long. Editing the registry may work, but you will have to do it on all client machines. You can use "recursive closure" as follows to alleviate the problem. It’s just a coding structure where you can work for a long time for a loop and change it into something that does some kind of work, and keeps track of where it stopped, giving way to the browser, and then continuing where it stopped until we let's finish.

Figure 1: add this Utility reuse class to your javascript file. You will not need to change this code:

 RepeatingOperation = function(op, yieldEveryIteration) { //keeps count of how many times we have run heavytask() //before we need to temporally check back with the browser. var count = 0; this.step = function() { //Each time we run heavytask(), increment the count. When count //is bigger than the yieldEveryIteration limit, pass control back //to browser and instruct the browser to immediately call op() so //we can pick up where we left off. Repeat until we are done. if (++count >= yieldEveryIteration) { count = 0; //pass control back to the browser, and in 1 millisecond, //have the browser call the op() function. setTimeout(function() { op(); }, 1, []) //The following return statement halts this thread, it gives //the browser a sigh of relief, your long-running javascript //loop has ended (even though technically we havn't yet). //The browser decides there is no need to alarm the user of //an unresponsive javascript process. return; } op(); }; }; 

Figure 2, The following code represents your code that calls "stop executing this script dialog" because it takes so long to complete:

 process10000HeavyTasks = function() { var len = 10000; for (var i = len - 1; i >= 0; i--) { heavytask(); //heavytask() can be run about 20 times before //an 'unresponsive script' dialog appears. //If heavytask() is run more than 20 times in one //javascript thread, the browser informs the user that //an unresponsive script needs to be dealt with. //This is where we need to terminate this long running //thread, instruct the browser not to panic on an unresponsive //script, and tell it to call us right back to pick up //where we left off. } } 

Figure 3. The following code is a fix for the problematic code in Figure 2. Note that the for loop is replaced by a recursive closure, which transfers control back to the browser every 10 iterations of the heavy mask ()

 process10000HeavyTasks = function() { var global_i = 10000; //initialize your 'for loop stepper' (i) here. var repeater = new this.RepeatingOperation(function() { heavytask(); if (--global_i >= 0){ //Your for loop conditional goes here. repeater.step(); //while we still have items to process, //run the next iteration of the loop. } else { alert("we are done"); //when this line runs, the for loop is complete. } }, 10); //10 means process 10 heavytask(), then //yield back to the browser, and have the //browser call us right back. repeater.step(); //this command kicks off the recursive closure. }; 

Adapted from this source:

http://www.picnet.com.au/blogs/Guido/post/2010/03/04/How-to-prevent-Stop-running-this-script-message-in-browsers

+11
Jul 23 '12 at 7:18
source share

In my case, during video playback, I had to call the currentTime function for video updates each time. So I used the timeupdate event for the video, and I found out that it was released at least 4 times per second (depending on the browser you are using, see this ). So I changed it to call a function every second like this:

 var currentIntTime = 0; var someFunction = function() { currentIntTime++; // Do something here } vidEl.on('timeupdate', function(){ if(parseInt(vidEl.currentTime) > currentIntTime) { someFunction(); } }); 

This reduces the number of calls to someFunc at least 1/3 , and this can lead to your browser behaving normally. It was for me!

+1
Jul 13 '15 at 18:27
source share

I can not comment on the previous answers, since I have not tried them. However, I know that the following strategy works for me. It's a little less elegant, but it does the job. It also does not require breaking the code into pieces, as, for example, some other approaches. In my case, this was not an option, because my code had recursive calls to logic that was looped; those. there was no practical way to simply jump out of the loop, and then you can somehow resume using global vars to maintain the current state, since these global variables can be changed by referencing them in a subsequent recall. Therefore, I needed a simple way that would not give the chance to the code to compromise the integrity of the data state.

Assuming "stop script?" the dialog appears during the execution of the for () loop after several iterations (in my case about 8-10), and messing with the registry is not an option, there was a fix (for me, anyway):

 var anarray = []; var array_member = null; var counter = 0; // Could also be initialized to the max desired value you want, if // planning on counting downward. function func_a() { // some code // optionally, set 'counter' to some desired value. ... anarray = { populate array with objects to be processed that would have been processed by a for() } // 'anarry' is going to be reduced in size iteratively. Therefore, if you need // to maintain an orig. copy of it, create one, something like 'anarraycopy'. // If you need only a shallow copy, use 'anarraycopy = anarray.slice(0);' // A deep copy, depending on what kind of objects you have in the array, may be // necessary. The strategy for a deep copy will vary and is not discussed here. // If you need merely to record the array orig. size, set a local or // global var equal to 'anarray.length;', depending on your needs. // - or - // plan to use 'counter' as if it was 'i' in a for(), as in // for(i=0; i < x; i++ {...} ... // Using 50 for example only. Could be 100, etc. Good practice is to pick something // other than 0 due to Javascript engine processing; a 0 value is all but useless // since it takes time for Javascript to do anything. 50 seems to be good value to // use. It could be though that what value to use does depend on how much time it // takes the code in func_c() to execute, so some profiling and knowing what the // most likely deployed user base is going to be using might help. At the same // time, this may make no difference. Not entirely sure myself. Also, // using "'func_b()'" instead of just "func_b()" is critical. I've found that the // callback will not occur unless you have the function in single-quotes. setTimeout('func_b()', 50); // No more code after this. function func_a() is now done. It important not to // put any more code in after this point since setTimeout() does not act like // Thread.sleep() in Java. Processing just continues, and that is the problem // you're trying to get around. } // func_a() function func_b() { if( anarray.length == 0 ) { // possibly do something here, relevant to your purposes return; } // -or- if( counter == x ) // 'x' is some value you want to go to. It'll likely either // be 0 (when counting down) or the max desired value you // have for x if counting upward. { // possibly do something here, relevant to your purposes return; } array_member = anarray[0]; anarray.splice(0,1); // Reduces 'anarray' by one member, the one at anarray[0]. // The one that was at anarray[1] is now at // anarray[0] so will be used at the next iteration of func_b(). func_c(); setTimeout('func_b()', 50); } // func_b() function func_c() { counter++; // If not using 'anarray'. Possibly you would use // 'counter--' if you set 'counter' to the highest value // desired and are working your way backwards. // Here is where you have the code that would have been executed // in the for() loop. Breaking out of it or doing a 'continue' // equivalent can be done with using 'return;' or canceling // processing entirely can be done by setting a global var // to indicate the process is cancelled, then doing a 'return;', as in // 'bCancelOut = true; return;'. Then in func_b() you would be evaluating // bCancelOut at the top to see if it was true. If so, you'd just exit from // func_b() with a 'return;' } // func_c() 
0
Jun 26 '13 at 14:46
source share



All Articles