JPM
JPM

Reputation: 93

Best way to solve this "ReferenceError: Function is not defined"?

I have an AEM page with multiple components, these components have a .js file with a function that encloses all the client side logic. We then call that function inside the component's HTML:

<script>
    window.bootstrap_component(function() {
        init_component_name();
    });
</script>

As stated before init_component_name is the name of a function that encompasses all the logic we need:

function init_component_name() {
    //DO STUFF
}

The wrapper bootstrap_component fuction is defined in the shared head.html of all our pages as:

<script>
    window.bootstrap_component = function (handler) {
        if (typeof handler === 'function') {
            if (document.readyState === "complete" || document.readyState === "loaded" || document.readyState === "interactive") {
                handler();
            } else {
                document.addEventListener("DOMContentLoaded", function() {
                    handler();
                });
            }
        }
    }
</script>

This works okay and we don't have any actual issues but we recently started using Bugsnag for error monitoring and reporting and we're getting reports for almost every component saying ReferenceError on page so/and/so init_component_name() is not defined.

The reason I think this is happening is because the init_component_name() function is not declared within the script tag and because this, function(init_component_name) has been attached to the window object it is executing fine and you don't see any console errors.

If I am correct would modifying those scripts tags to be like this work?

<script>
    window.bootstrap_component(function() {
        window.init_component_name();
    })
</script>

A colleague of mine wants to add a timeout to the init_component_name functions of like 1ms but it rubs me the wrong way. Is there a more sensible approach?

Upvotes: 0

Views: 1312

Answers (1)

Mitya
Mitya

Reputation: 34556

If I am correct would modifying those scripts tags to be like this work?

window.bootstrap_component(function() {
    window.init_component_name();
})

Yes, but you then have the problem that you're writing multiple data to the global namespace, window, which isn't ideal. What if another third-party script decides to override it?

Ideally you'd have a single namespace and put everything on there, and write only that namespace to window.

window.something = {};
something.bootstrap_component = { //...

and

something.init_component_name = () => {
    //DO STUFF
}

Or better still, use modules (though that will need some light code refactoring).

Don't do the timeout hack. It's really, really horrible; what if scripts take longer than a second to load for some reason? You're also forcing your UI to wait a second, often unnecessarily. This hack tends to feature where chronology and scope has not been thought out properly.

Upvotes: 2

Related Questions