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.
Related
I'm debugging a userscript, which is hard to debug, because the bug happens rarely and unpredictably (yet), and the function stack gets executed repeatedly (and the bug happens approximately once every 10-20 times). I cannot pause the devtools, otherwise the page will reload and the bug won't appear (so I cannot use breakpoints). Edit: even if I stop the page from reloading I still have to make user-input repeatedly and fast to cause the bug, so not possible to use breakpoints, because that would stop the bug from appearing.
One of the ways which I can think of is putting console.log in every function and logging variables and then searching through them to find where it went wrong. But it seems very tedious. In the performance section of devtools it's possible to record the process, and see the function calls, but it's impossible to see the variables.
Is there any way to go through the function call stack post-factum (maybe a tool other than devtools), seeing what the variables were equal to in every cycle? (And not only the current call stack, because it gets updated on every user input in my script). Or is console.logging my only option in this case?
I thought that "step out of the current function" option would work, but it seems to be unpredictable (it seemed to happen at least when there is setTimeout). And the function stack gets updated on every user input (and to capture this bug the user input sequence should be fast), so there is no way to go through the call stack either.
It would be perfect to have something like a call stack tree, which would show when a certain function was last called (and how many times during a certain period of time or since the page load), what was the position of this function in the tree of all functions, and the ability to go through this tree and search for all instances of calls to a specific function, and then the ability to see what the variables were equal to in every call.
There is a lot of code, but since it was requested, here is a link to the code inside a GitHub repository (it's a Chrome Extension, and the code where the bug happens is inside the objGA object [at the 6490's line of code]). And the bug happens somewhere between the 6600's line and the 6890's (the bug is that sometimes it doesn't move chess pieces on premoves). It's a Chrome Extension to move chess pieces with a keyboard and a mouse.
https://github.com/Sentero-esp12/Lichess-Keyboard-WebRequest-/blob/master/Extension/code.js
Edit:
Luckily I was able to reproduce it in a slow pace with breakpoints (was able to find the exact moment when the bug appeared). So it turned out I was using Math.round instead of Math.floor trying to extract the first digit from a double digit number. Since only some numbers were >= *5, the bug appeared only occasionally and I couldn't notice the cause.
I'll pick Chrome for this example, but I'm open to a solution from any browser.
Use Case:
I have an update button on my website that is used to update item quantities in a shopping cart. I'd like to allow a user to enter a 0 and click update in order to remove the item. Trouble is, there is some listener in some js function that is denying the ability to enter a 0 and click update (after clicking update the old quantity remains).
My question is, what developer tool can I use to find which js function is running during that event? I don't think that Chrome's inspector does this, and I'm not very familiar with Firebug, but I couldn't find the functionality there either.
I feel that I should be able to inspect js firings just like I do css stylings. Is anyone aware of a tool I may use?
I've had to debug some particularly nasty unseen-cause Javascript issues at my job. Knowing the full depth of developer tools like Chrome's is definitely helpful. It undeniably takes some creativity to find places that might be causing the issue, but a few tips:
Tracking down event listeners
Under Chrome's Elements view, try Inspect-ing an element (right-click, Inspect); then, on the right side of the developer view, scroll down to Event Listeners. Here you can view what code files have hooked up an event. Often, this will just point you to a middle-framework from the really devious code you're looking for, but sometimes it will point you in the right direction.
Trapping a DOM modification
Many of the unwanted effects I see are because of something changing some value or attribute on the page that I don't want. Anytime this happens, you can right-click on the element (under the Elements view) and say "Break on..." and the specific scenario you're looking for. When Chrome then hits a breakpoint, you can then look downward in the Stack Trace until you find something recognizable that shouldn't be called.
EDIT after reaching ten votes!
Trapping a JS object modification
If the change you're interested in is code-internal, not in the UI, things get trickier. What's meant by this scenario is that you know somewhere in the code, something incredibly annoying like the following is happening.
company.data.myObject.parameter = undefined;
In this situation, you know myObject is still the same object, but it's being modified, perhaps unintentionally. For that, I often insert the following bit of code, sometimes just through the developer console at some point before said modification happens.
Object.defineProperty(company.data.myObject, 'parameter', {
set: (val) => {
debugger;
}
});
This includes an arrow function - you're only using this for debugging and Chrome supports it, so might as well save keystrokes. What this will do is freeze your debugger as soon as some line of code attempts to modify myObject's "parameter" property. You don't necessarily have to have a global reference to the variable if you can run this line of code from a previous breakpoint that will have the given object in the locals.
Otherwise, if all I'm starting out with is the HTML code, and I want to tie that to Javascript code, I'll often just look for identifying features like "id" elements, and search all JS files in my development directory for it. Normally, I can reach it pretty fast.
Open your page in Firefox with Firebug enabled.
Go to console tab in firebug and click profiling
enter 0 in the textbox and click the button.
Stop profiling.
You will be able to see all the javascript functions which have executed due to your actions. You can view them one by one to figure out which method has caused the mischief.
Go to you code. If you are using jQuery there is going to be a function that will be called with the class or id of that particular update button. Or, if you are using Javascript, there is going to be a function called inside the
<input type="button" name="update" onclick="update()">
These are the two ways to look for the function that is being called; there is no software that I know
Download Firebug for Mozilla Firefox, open it, click on Net and refresh your website. Than, you can see which files are loaded on the page.
If you want to check on errors and what goes wrong with an explanation, than click on console and refresh the page once again. You will see the errors and on which line it goes wrong.
Note: in your console, you can say hold or stop, so that the js file stops loading. And you can edit the script by clicking on script in Firebug. Debugging is simple, as it says on their official page https://getfirebug.com/javascript
Let's say we got an onClick event to a certain div, but before that, we have a big calculation that needs to be done with jQuery which takes like 3 seconds and jQuery is currently busy so it doesn't recognise my event call.
So, 1 second passes and I click on the box. Nothing happens? 2 second. Nothing happens? 3 seconds and jQuery completes his current task. My onclick jQuery event works and the box disappears.
The question is;
What would jQuery do in this case? Automatically create a thread to execute my onclick event instantly? Queue the call? (so it would execute my 3 clicks when the task done, hence 3 event calls) Ignore the first 2 call completely? Also, what should I do to avoid this kind of problems?
JavaScript functions as if it were single threaded. It's my understanding that some browsers differ in actual implementation, but it is safe to write your scripts with the expectation that they will be executed linearly.
See this Question
I imagine your browser will queue up the clicks during the blocked UI, but it's up to the browser to decide how to handle that scenario. (My Chrome queues up click events during blocked UI)
That said, there's a cool feature implemented in newer browsers:
Web Workers
It allows you to perform expensive/long operations in the background without blocking UI. If your script is going to be running on mostly new browsers, it might be worth digging into this feature. BONUS: that article is written by the originator of jQuery! =)
You could probably use a loading bar or a page refresh element to inform the user that something is happening in the background .
Have a look at this jsfiddle. On Chrome, as Shad stated, the clicks get queued up and the events are handled when the calculation has finished. One weird thing is that the line before the big calculation
E('status').innerHTML = "Status: started";
doesn't seem to get executed until afterwards. Another surprising thing is how easy it is to make the entire browser hang by repeating a few operations 10,000 or 100,000 times.
If a server side solution is not possible, a solution could be to break the calculation down into smaller batches of operations, and carry them out one batch at a time with an interval of a few milliseconds to allow other parts of the code to operate. In the meantime you might need a 'please wait' message.
I have a grid of pictures (3x3, side by side, laid out in a ). I need to update this grid every so often. Since every picture independent from the rest (they get grabbed from different locations), I elected to load every picture by its own ajax callback, like so:
for (var i=0; i < numPictures; i++) {
Dajaxice.loadPicture(callback_loadPicture, {'picture_id':i})
}
The function callback_loadPicture() puts the picture into its proper place in the .
The problem is: Often, even though some picture will finish loading sooner than others, the browser will not display anything until the last ajax call is finished. Since some calls can time out, this means that I don't see anything until that single picture times out.
This behaves slightly differently in every browser: sometimes the picture will show as the callbacks finish (but usually not), sometimes the browser will show some images, but postpone showing all until the last one is finished loading.
I am using:
django 1.3 (python 2.7)
windows x64 as (test) server
dajaxice for ajax implementation
I am open to changing the structure of my code.
Any comments or suggestions will be appreciated.
Since the ajax calls are blocking as said by chrisdpratt, if you really need to display the images at the same time I would advise some kind of preloading of the 3x3 grid of images and when required by the code you can display them.
With this in mind you can run the code you already have on $(document).ready() but make the images hidden (ie display:none). When later required you would just change the display attribute on the images you need to display.
If the issue you were seeing was indeed caused by the single-threaded implementation of the Django development server, you might try django-devserver (https://github.com/dcramer/django-devserver). Amongst other improvements, it boasts:
"An improved runserver allowing you to process requests simultaneously."
The other improvements make it worth it, too!
Is JavaScript intended to be running as little as possible on a website/webapp? By that I mean is the usual intention to run through all your js files as soon as the page loads and put them aside, and then when functions come up to execute them right away and be done with it?
I'm working on a project using google maps and I have a custom marker object scripted out, and a debugger has told me that the browser runs through all my js files before anything even appears on the page.
My problem comes in here: I wanted to animate certain markers to bounce up and down continuously with jQuery (similar to OS X icons in the dock) and my several attempts at infinite loop functions all just crash the browser. So I understand that the browser doesn't like that, but is there a way to have a simple script be repeating itself in the background while the user navigates the page? Or is JavaScript just not supposed to be used that way?
(I worked with Flash for a long time so my mindset is still there.)
Yes, Javascript functions should just do their bit and exit as soon as possible. The GUI and the scripts run on the same single thread, so as long as you are inside a Javascript function, nothing shows up in the browser. If you try to use an infinite loop, the browser will appear to freeze.
You use the window.setInterval and window.setTimeout methods to trigger code that runs at a specific time. By running an interval that updates something several times a second, you can create an animation.
You have to set a timer to execute a script after a defined time.
var timer = setTimeout(code, milliseconds);
will execute code in so-and-so milliseconds. Each execution of the script can set a new timer to execute the script again.
You can cancel a timed event using clearTimeout(timer).
Use setTimeout() or setInterval(). The MDC articles on it are pretty good.
You'll need to update inside of functions that run quickly, but get called many times, instead of updating inside of a loop.
Since you said that you are using jQuery, consider using its effects API (e.g., jQuery.animate()), it will make your life much easier!
Personally, I save as much code as possible for execution after the page has loaded, partly by putting all my <script>s at the bottom of <body>. This means a (perceived) reduction in page load time, whilst having all my JS ready to run when need be.
I wouldn't recommend going through everything you need to do at the beginning of the document. Instead, bind things to events such as clicks of buttons, etc.