Can someone debug a progress bar issue in my Javascript applet? - javascript

Here is the applet
You can leave all the settings as they are, then hit "Calculate". After a few seconds, you should see some plots show up, then the progress bar below the "Calculate" button will fill up to 100%.
The problem is that I'd like the progress bar to increment while the code is running, not after it has completed as the plots are made. I know the code is long, but you can search for the following progress bar code:
setTimeout( update(count++, L.length, f.length, phi.length) );
It accesses the function update(s,x,y,z) which is defined directly before the main calculate() function.
I'm just confused as to why the progress bar doesn't update until all the processing is complete.
Thanks in advance!

The problem you observe is caused by javascript's single-threaded nature. Timeouts do not get executed while existing code is being executed. Web workers were introduced to deal with just that type of restriction. If you are unable to use web workers(e.g. due to IE limitations), using timeouts is the only way to emulate multythreading.
To check that, you may replace your line with update(count++, L.length, f.length, phi.length)() and change update to log values into console.
As for current update implementation, I suppose either there are some any mini timers inside jquery, causing the issue, or browser rendering capabilities are just not available for some reason:).
The reason is that your calculations and drawings take far less time than timeout. Therefore by the time timeout functions are executed, everything has already been drawn.
You could verify that by replacing your line with update(count++, L.length, f.length, phi.length)() - it will lead to instant update up to 100%.
To get progress bar work more precise you should review your calculation code and try rewriting it in a chunk-friendly manner. I mean having a possibility to execute calculations chunk by chunk and updating progress bar at the end of each chunk. Having that done, you could use timer to evaluate everything.
Sample:
(function(){
var arr = [1,2,3,4];
(function popLog(){
console.log(arr.pop());
if (arr.length > 0){
setTimeout(popLog, 100);
}
})();
})()
Another approach is using web workers, querying the status from time to time and updating progress bar appropriately. However, IE does not support them.

Related

using requestanimationframe, profiling shows >80% time spent idle, still getting 4fps. why? (/how to fix?)

I have a simple canvas game. It's architected with a simple requestAnimationFrame loop that updates the state, and then renders to the canvas (simple!). It runs really well on desktop + iOS, but on chrome on android, it runs terribly.
Here's the loop, for example:
var tick = function()
{
requestAnimationFrame(tick,canvas);
cur_scene.tick();
cur_scene.draw();
}
So I pulled up the remote profiler, recorded a quick session, and over (any given) 1 second, it shows ~.82s idle (.11s scripting, .04s 'other', .02 painting, .005 rendering).
It also shows ~.1s per frame (the space between consecutive Animation Frame Fired entries on the flame graph). But the flame graph is like (consistent with the other measurements) 80% empty?
So I'm at a loss- what can I do to get this to render at a higher framerate? Am I reading the diagnostic info incorrectly? Have I structured the requestAnimationFrame loop incorrectly?
Edit: Here's an annotated picture of some of the performance diagnostics (picked up by recording a remote session on my android phone)
I think you could try to put the call to requestAnimationFrame() at the end of your method like this:
var tick = function()
{
cur_scene.tick();
cur_scene.draw();
requestAnimationFrame(tick,canvas);
}
Else you might end up entering the loop again without drawing anything but requesting the animation frame again.
When you check the following example, they also first do their changes to the object before they call requestAnimationFrame():
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
The above documentation explains this in the following text:
The method takes a callback as an argument to be invoked before the repaint. [...] You should call this method whenever you're ready to update your animation onscreen.

Javascript Animation and Recursion

I have written a Javascript program that solves a puzzle game using a recessive technique.
That is, function solvePuzzle() calls function solvePuzzle() for a simpler puzzle until the solution is found. It alters the data in the board object.
I also have a function board.draw() that can display the state of the puzzle
It draws the initial game board as I expect and once I click on a button (triggering execution of solvePuzzle()) it draws the solved game board again as I expect.
However, I would like to show the intermediate puzzle states.
Initially, I inserted calls to board.draw() in the solvePuzzle() function but this does not do anything.
Researching Javascript animation has led me to create and execute this function
function animationLoop(timestamp) {
// 1 - Clear
ctx.clearRect(0, 0, c.width, c.height);
// 2 Draw
board.draw();
pieces.draw();
// call again mainloop after 16.6 ms (60 frames/s)
requestId = requestAnimationFrame(animationLoop);
}
requestId = requestAnimationFrame(animationLoop);
I am confident this is working as this only place I now call board.draw() and it show the initial state and switches to show the solved state after I press the solve button but... still no intermediate states are shown.
I then hypothesised the issue was that solution was so quick that it happens between frames but discounted this by placing this 'delay' in solvePuzzle
if (solutionCount%1000 == 0) {
confirm("Are you sure you wish to continue?");
};
I am now hypothesising solvePuzzle must run to completion before animationLoop can progress.
Is this hypothesis correct?
If so, how can I resolve my issue?
I am thinking I sort of need to continually end and resume my reclusive function at each state but cannot get my head around how I might do this.
Note: another reason I am confident the animation is working is that if I alter board from the console with say a statement like
board.layout[7].available = true;
the expected change is made to the display
JavaScript is single-threaded, and shares this thread with UI updates. Thus, when a function is started from top level, the browser does not do anything else until that function exits. This includes animation frame - animation is happening any time the page's thread is idle and an animation can be scheduled, but while your code is executing it can't.
If your calculation takes time, you need to split it into discrete pieces and let the browser breathe in between if you want UI updated (normally using setTimeout(f, 0), or inside requestAnimationFrame handler).
Another possibility is using Web Workers. They are a way to launch JavaScript in a separate thread. However, they cannot interact with the DOM at all, and can only communicate with messages. So, you can launch your calculation in a Web Worker, then from the worker periodically send messages to your main JS code in order to make it update the DOM in accordance to the results (both interim and final).
Thanks Alexander O'Mara and Kaiido for making me cover cases I forget.

Why is Alert working as a pause?

First of all, apologies if this question was answered before.
I'm writing a code in JS to read an Excel File, get the value of the first cell in the column, search for it (it's an ISBN code, which I'm searching with the Google Books API) and get other relevant info, made available through the search (like Title, Subtitle and Author), then proceed to the next line and repeat the process.
My problem is writing the new data back in the Excel File. The code is writing all info in the last used row in the file. While using window.alert to flag the code, I noticed that when the alert was in a for loop, right before the search was initiated, the new data was inserted just fine, but if I tried to use a pause (like a timer function or a while loop to consume time) it didn't help at all.
What I want to know is why that behavior might be happening and, if possible, of course, a possible solution for my problem, since having to use alert as a pause isn't exactly the most interesting solution.
Thanks in advance
Alert will always stop all execution of code, except for web workers. Therefore, If you need to continue execution, use a web worker. Have a look at this for reference (the note part covers this topic partially)
When browsers show a native modal interaction widget, such as an alert, it transitions into a state that waits for the response. In this state, it is allowed to redraw the page and process certain low level events. Here's the code from Mozilla Firefox that alert() and confirm() use:
http://mxr.mozilla.org/mozilla-central/source/toolkit/components/prompts/src/nsPrompter.js#434
This openRemotePrompt function doesn't return until the user clicks "OK" on the alert. However browser behaves differently while the alert is open. A loop repeatedly calls thread.processNextEvent to do certain kinds of work until the dialog is closed. (It doesn't run the application's JavaScript code, since that's meant to be single-threaded.)
When you use a pure JavaScript busy wait, for example, by looping until a certain wall time, the browser doesn't take these measures to keep things moving. Most noticeably, the UI won't redraw while the JavaScript code is looping.

What in JavaScript can cause browser crashes?

I have an application that a wrote in straight JavaScript (no jQuery or anything). What it does is it uploads an image, and when you click on it, it gets the dominant colors of the image as well as picks the color you just clicked in the image, and generates a color scheme based on this.
I have part of it implemented here: http://cassidoo.co/assets/colordetect/index.html (this version only has the color detection part, not the color picker/color scheme part)
Now, I'm trying to figure out some issues. The application usually works. The only time it doesn't work is when the browser crashes. I looked at the thread here:
How can I test potentially "browser-crashing" JavaScript?
And I've been using my debugger and everything, but I'm not actually getting any errors when the browser crashes. It just suddenly isn't responsive and after a little while I get the "Oh, Snap" screen or something.
How can I debug this? What in my code might be freaking out (like is it an infinite loop I'm not closing, something with the canvas that's not normal)? Why does it only happen like 50-60% of the time? Is it a cache issue?
Do you have particular test images which always make it crash? If so, can you upload them somewhere so we can test with them?
I'm finding that it always crashes when trying to process an animated GIF. Using Chrome's debugger, I can see that it's getting into an infinite loop in the while (true) loop in k_mean(). The break condition diff < min_diff is never happening. Something's going wrong in the code, because diff is always NaN (not a number).
A good way to debug it is to set breakpoints at various places in the code, look at the state of the variables each time a breakpoint is triggered, etc. The profiler in Chrome can also be useful, by showing you where the execution time is being spent.
It probably is an infinite loop. You can test that by putting a condition in your loop that throws an alert or console-log after 100 loops (or whatever) and halts execution.
Any tricky regular expressions? Catastrophic backtracking can bring you down too. http://www.regular-expressions.info/catastrophic.html
And as mentioned above, too many recursions will also. Any functions calling themselves repeatedly?
You could always do something like this:
var foo = "bar";
while (1) {
foo = foo += "bar"; // adds until memory is full, then crashes (womp womp)
}
Here are some of the things that could cause browser crashes, although I am not sure if they are causing your problem.
Anything while(1) (infinite loop) - Browsers cant seem to handle these
Variable with too much data (out of memory - plausible if storing big images)
Trying to reload too many times (like infinite loop of realoads)
SetInterval to SetInterval To SetInterval etc... (this is more silly than a guess)
Probably an infinite loop or just a weird while. I hope you get it fixed!
Simplest way:
while(1)location.reload()
It works by creating an endless loop, then refreshes the page until the browser crashes.
Note: it instantly freezes and you can not see it refreshing.
Try it for yourself:
https://send-as-mail.000webhostapp.com/

Page elements don't visibly update during load

I'm probably missing something really obvious here...
I'm showing a dialog box with progress bar during page load. The dialog and progress bar are both jQueryUI widgets. There are a couple of phases of loading - the page makes a load of jQuery $.get() requests to load resources, then on the $(document).ajaxStop() event, does things with those resources. I'm updating the progress bar and some status text throughout this process.
The issue is that as soon as the ajaxStop event fires, updates stop. The code works nicely during resource loading, but then freezes and I don't see any of the updates during processing. If I put a breakpoint on a post-ajaxStop update in Chrome and step through the code, the screen updates correctly so I know that the code works.
Can anyone explain why everything updates nicely during my AJAX loading phase, but then stops on the ajaxStop event? Is there an easy way to make updates continue afterwards?
Thanks!
Several hours of searching later, the following blog pointed me in the right direction:
There's a jQuery extension described in the entry which allows you to define two functions, one to compute and one to update the UI. It schedules them alternately using the setTimeout function.
I've had to rewrite my code in something akin to continuation passing style so that each function schedules its continuation to run using setTimeout. This returns control to the browser for long enough for the screen to be updated.
This feels like a bit of a hack though to get round browser/Javascript limitations. Anyone know of a better way?

Categories

Resources