Select to view content in your preferred language

"Uncaught ReferenceError: require is not defined" when adding JSAPI after page load

5474
2
Jump to solution
05-28-2013 08:55 AM
BradCollins
Emerging Contributor
I am using DOM manipulation to add the following (comments not included; I add them here for clarity):

<!-- ArcGIS JSAPI --> <script async="false" src="http://serverapi.arcgisonline.com/jsapi/arcgis/3.4compact/"></script> <!-- my application --> <script async="false" src="js/index.js"></script>


to an HTML page after it has loaded. I receive the following error:

Uncaught ReferenceError: require is not defined


when the browser attempts to run index.js, which begins with a require block this way:

var app;  require([     "dojo/ready",


Why am I doing it this way? I am writing a PhoneGap app that runs on an iPad. One requirement of our application is that it run on a private network without access to the Internet. Consequently the location of ArcGIS JSAPI is not fixed.

To handle this problem, I have a Settings bundle that allows the user to set, among other things, the server URL of the ArcGIS server where the JSAPI resides. Then I have some bootstrap JavaScript code that reads the values from the Settings bundle and loads the ArcGIS JSAPI from the location the user has specified:

    function loadScripts(javascripts) {       console.debug("Loading JS");              var arcgisJs = [config.arcgisServerUrl + "/jsapi/arcgis/3.4compact/"],           allJs = arcgisJs.concat(javascripts),  // add other scripts, in this case, index.js           head = document.querySelector("head");                  allJs.forEach(function (jsUrl) {         var tag = document.createElement("script");         tag.setAttribute("async", false);         tag.setAttribute("src", jsUrl);         head.appendChild(tag);       });        console.debug("Finished loading JS");     }


In other words, I load the JSAPI and then my application script (index.js), both of them with async="false". Any ideas why "require" is not defined since I load index.js after the JSAPI?
0 Kudos
1 Solution

Accepted Solutions
BradCollins
Emerging Contributor
I got it working with a bit of a hack suggested by a coworker. Apparently there is some asynchrony going on: require is eventually defined, but it isn't at the time my app initialization code starts running. So I check the "require" variable every 50 ms and move on when it finally is defined:

  function waitForRequireToBeDefinedThenProceed() {     if ("undefined" == typeof require) {       console.debug("'require' still not defined. Waiting ...");       setTimeout(waitForRequireToBeDefinedThenProceed, 50);     } else {       console.debug("'require' finally defined. Moving on.");       defineAndInitializeApp();     }   }


I should still be glad for a more elegant solution if anyone has a suggestion.

View solution in original post

0 Kudos
2 Replies
BradCollins
Emerging Contributor
I got it working with a bit of a hack suggested by a coworker. Apparently there is some asynchrony going on: require is eventually defined, but it isn't at the time my app initialization code starts running. So I check the "require" variable every 50 ms and move on when it finally is defined:

  function waitForRequireToBeDefinedThenProceed() {     if ("undefined" == typeof require) {       console.debug("'require' still not defined. Waiting ...");       setTimeout(waitForRequireToBeDefinedThenProceed, 50);     } else {       console.debug("'require' finally defined. Moving on.");       defineAndInitializeApp();     }   }


I should still be glad for a more elegant solution if anyone has a suggestion.
0 Kudos
KonstantinLapine
Emerging Contributor
I got it working with a bit of a hack suggested by a coworker. Apparently there is some asynchrony going on: require is eventually defined, but it isn't at the time my app initialization code starts running. So I check the "require" variable every 50 ms and move on when it finally is defined:

  function waitForRequireToBeDefinedThenProceed() {
    if ("undefined" == typeof require) {
      console.debug("'require' still not defined. Waiting ...");
      setTimeout(waitForRequireToBeDefinedThenProceed, 50);
    } else {
      console.debug("'require' finally defined. Moving on.");
      defineAndInitializeApp();
    }
  }


I should still be glad for a more elegant solution if anyone has a suggestion.


You could assign a callback to the script.onload event handler. Example (I just posted it in another thread but realize it would be more relevant here):

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="https://community.esri.com//js.arcgis.com/3.9/js/dojo/dijit/themes/claro/claro.css">
        <link rel="stylesheet" href="https://community.esri.com//js.arcgis.com/3.9/js/esri/css/esri.css">
        <script>
            function onLoadScript() {
                'use strict';

                require(
                    [
                        'dojo/parser',
                        'esri/map'
                    ],
                    function () {
                        function init() {
                            var map,
                                service;


                            map = new esri.Map('map');

                            service = new esri.layers.ArcGISTiledMapServiceLayer(window.location.protocol + '//server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer');

                            map.addLayer(service);
                        }

                        dojo.parser.parse();

                        init();
                    }
                );
            }

            function loadScript(src, callback) {
                'use strict';

                var script,
                    scriptsrc,
                    scriptTag;

                script = document.createElement('script');
                script.type = 'text/javascript';

                scriptsrc = window.location.protocol;

                scriptsrc += '//' + src;

                script.src = scriptsrc;

                script.onreadystatechange = function () {
                    if (this.readyState === 'complete' || this.readyState === 'loaded') {
                        callback();
                    }
                };

                script.onload = callback;

                scriptTag = document.getElementsByTagName('script')[0];
                scriptTag.parentNode.insertBefore(script, scriptTag);
            }

            loadScript('js.arcgis.com/3.9compact', onLoadScript);
        </script>
    </head>

    <body class="claro">
        <div id="map"></div>
    </body>
</html>
0 Kudos