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.
Related
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.
So I want to migrate all my javascript functions to requireJS and will try to use as much as possible the ondomready event. BUT:
this will freeze the browser, since all javascript is synchronously. This is bad. I mean wow the user sees the browser content a bit faster, but is going to try to click somewhere just to realize the browser was frozen, and has to click again. This is very bad. Is there a way around this?
Patient: It hurts when I do this.
Doctor: Then don't do that.
If you see freezing on the dom ready event then perhaps you are trying to do too much. Executing javascript is quick. Doing a page redraw is slow.
Rather than lots of small events that each make changes to the dom and each cause a page redraw you should have one function that processes a list of changes that need to be made. This is what the domReady plugin does before the ready event. After the ready event it just runs them as it receives it which could cause multiple redraws.
I learnt this while writing my own animation library. I was using individual setInterval()'s to change a single property. When doing more that four a once the animation was no longer smooth. A better way to do this is a single interval that processes a list of changes that need to be made.
Edit:
Instead of using domReady as a plugin require(["domReady!"], use it as a module so that you can run initialisation code straight away then make changes to the dom later.
require(["domReady"], function(domReady) {
var element = document.createElement('table');
//more setup code
domReady(function(){
document.body.appendChild(element);
});
});
i need to run a function periodically regardless the page where i am. This function will get some data periodically.
I dont think that this works:
function myFunc()
{
//your code
}
//set the interval
setInterval(myFunc,2000) //this will run the function for every 2 sec.
Because it works only for the page where I am right now, so if i go to another page, function is not executed anymore.
I would like to write a function that start running when user is at index page and then is called periodically until user close the page.
Any idea? Thanks in advance!
That's not possible with javascript in the browser. When you navigate away from the page, the script will stop. You have to include a script on every page that initializes this periodical update. Or you could rewrite your application to a "single page application", which seems to be popular nowadays.
You'll need a backend application or cron-job to do that.
Another way do that would be to make an Ajax-only single page application. I guess twitter uses that model.
Depending on what your doing in the function you may be best to use a JS Worker which will run as a new thread and allow you to continue processing as much as you want in the background without having to worry about JS timeouts.
The main point here is what your asking for is near enough impossible within JS unless you use something similar to jQUery and dynamically load your pages in to a div? This would mean you still have the effect (visually) that you changing page but the browser only loads the data in.
Its very easy to in fact to load content in to a DIV using jQuery its:
$('#elementoloadid").load("/path/to/load");
You could achieve this without using jQuery but will take you longer.
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'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?