Preventing JavaScript Files from Loading Multiple Times

This post is about ensuring that you do not execute a particular JavaScript file more than one time. Let’s start by asking:

What happens if you link to a js file twice in your page?

Here is a contrived example.

Notice that we are including bad-example.js twice. Do modern browsers somehow realize they loaded this file already and skip this? Not yet, as we’ll see!

Imagine bad-example.js had this code in it.

Is jQuery smart enough to know it should only hook this event once per file? Will that divbe appended as many times as the file was included when the button named nameIt is clicked?

I’ve created a simple jsFiddle for you to explore this problem before we get to the solution.

Accidentally Included Script Three Times

In the bottom-right pane, you’ll see the web page running. Enter your name and click the button. You’ll see that you get this output, repeated 3 times per click!

Now, the old saying “I said, doctor it hurts when I do this with my arm. Doctor said, then don’t do that!” comes to mine. Maybe we should just try hard to not include a js file multiple times. In real web apps, it’s not that simple.

I’ve been working on a JavaScript-heavy web application recently. There are a lot of ASP.NET MVC views and layouts as well as a lot of JavaScript files. Currently, a little dir /s reports there are 1,200 razor views and 50 JavaScript files. Many of these are views nested within views which are nested within layouts, and so on. It’s not simple to be certain you’re only including a file once.

So what do you do? Give up and proclaim that JavaScript sucks. It was never meant for building large applications. No, of course not.

The web is awesome and the fix is simple enough.

Let’s look at another example. If we could simply write code like this, we would be in business.

We call fileAlreadyLoaded and bail out if it’s true. You’ll see that by using namespaces (you should do this anyway!) and a simple method which embraces JavaScript’s dynamic nature, we can pull this off easily.

First, for your project, define a global namespace. Let’s assume I’m writing a blog app. So maybe blog is a good base namespace. You see, in JavaScript it’s as simple as this:

This might be good for your main JS file. But you do not want to have just one huge JS file. Breaking things up for maintainability is good. So suppose we have a commets.js file. In there, we’d have:

Notice, it’s not var blog.comments.We’re adding a sub-namespace (object) to the global namespace blog. With namespaces in place, we can add methods to them and get intellisense to boot! Here’s an example of adding a method to the blog.comments namespace.

We can set values such as blog.comments.debugMode = false. And your code becomes much more navigable in Visual Studio with intellisense by leveraging namespaces:

So namespaces are great and all. But the question is…

How do we leverage namespaces for checking whether a file is loading more than once?

Well, if we use one namespace per file and recall that namespaces are just objects we can write that method to check for a double load like this:

We take a namespace and see if it has a firstLoad property. The first time, firstLoad has never been set, so it comes back as undefined. Hence, isFirst is true. We add a little logging to let us know there is trouble if it’s a second load. Then we just return the status.

Anywhere in your js file you need check (only ask once per file!) you can do:

See how we pass the namespace blog.comments which is in the comments.js file?

There you have it. We prevented the execution of a JS file the second, third, etc times it’s included. You even get a diagnostic output to boot.

So for the final part of this post, check out a new jsFiddle which uses the improved script with this testing and with namespaces.

Scripts only once (block multiple)

Now you see, we get just the output we want. Our script was included 3 times and yet it only ran once.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s