SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    SitePoint Member
    Join Date
    Jan 2005
    Location
    melbourne
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    object instantiation in firefox

    Howdy,

    I've got some javascript that is dynamically loaded from an external file. My question is: at what point are any objects defined in that file available for instantiation in the calling script? When I try to instantiate the Test object (via a button) in the script below in Firefox 1.0 I get a ReferenceError. If I click the button a second time it works.

    A cut-down example follows, the main difference being that in my actual code I don't know ahead of time what the name of the object that I need to instantiate is (which is where eval comes in handy).

    You've got a file 'test.js' which contains
    Code:
    function Test(v) {
        this.val = v;
    }
    
    Test.prototype.getVal = function() {
        return "Value is: " + this.val;
    };
    Then another file called test.html which contains:
    HTML Code:
    <html>
    <head>
        <script type="text/javascript">
        function loadScript(sid) {
            var retval = "script " + sid + " ";
            if (!document.getElementById(sid + 'Script')) {
                script = document.createElement('script');
                script.setAttribute('src', sid + '.js');
                script.setAttribute('type','text/javascript');
                script.setAttribute('id', sid + 'Script');
                document.getElementsByTagName('head')[0].appendChild(script);
                retval += "loaded";
            } else {
                retval += "already present";
            }
            return retval;
        }
    
        function tryIt() {
            var retval = "loading script\n"; 
            retval += loadScript("test") + "\n"; 
            var obj = null; 
            try {
                obj = new Test("success"); 
            } catch (e) {
                retval += e + "\n";
            } 
            if (obj) {
                retval += obj.getVal() + "\n";
            }
            alert(retval);
        }    
        </script>
        </head>
        <body>
            <form>
                <input type="button" value="try it" onclick="tryIt();"/>
            </form>
        </body>
      </html>

  2. #2
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    ...at what point are any objects defined in that file available for instantiation in the calling script?
    The file has to be downloaded, parsed, and the objects created... so we must wait for it. For quick convenience I made 'retval' global. Then put the object creation code in another function, tryIt2, which waits for the object to become not undefined. Out of curiosity I added the 'count' variable.
    Code:
    <html>
    <head>
        <script type="text/javascript">
    
        var retval;
        var count = 0;
        
        function loadScript(sid) {
            retval = "script " + sid + " ";
            if (!document.getElementById(sid + 'Script')) {
                script = document.createElement('script');
                script.setAttribute('src', sid + '.js');
                script.setAttribute('type','text/javascript');
                script.setAttribute('id', sid + 'Script');
                document.getElementsByTagName('head')[0].appendChild(script);
                retval += "loaded";
            } else {
                retval += "already present";
            }
            return retval;
        }
    
        function tryIt() {
            count = 0; // mf
            retval = "loading script\n"; 
            retval += loadScript("gbc") + "\n"; 
            tryIt2();
        }    
        function tryIt2() {
            if (typeof Test == 'undefined') {
              setTimeout('tryIt2()', 10);
              ++count;
              return;
            }
            var obj = null; 
            try {
                obj = new Test("success"); 
            } catch (e) {
                retval += e + "\n";
            } 
            if (obj) {
                retval += obj.getVal() + "\n";
            }
            alert(retval + '\n\ntryIt2 was called ' + count + ' time(s).');
        }
        </script>
        </head>
        <body>
            <form>
                <input type="button" value="try it" onclick="tryIt();"/>
            </form>
        </body>
      </html>
    Last edited by MikeFoster; Jan 7, 2005 at 08:27. Reason: Added the line with comment "// mf" so count will be correct when running the test the second time.

  3. #3
    SitePoint Member
    Join Date
    Jan 2005
    Location
    melbourne
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Mike,

    I guess what threw me was that the object was always available on the first call in IE.

    Would you consider this a bug in firefox i.e. that scripts loaded in this fashion are parsed on seperate thread to the main execution thread?

  4. #4
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No, I wouldn't consider it a bug. I think all three browsers I tried worked the same way.

    Using the 'count' variable, and only testing locally, I saw...

    Opera 7.51: count = 1
    Mozilla 1.7.2: count = 1
    IE 6: count = 0

    I'm using Win2K. As we know, IE is more integrated into the OS than Opera or Mozilla.

    For me, I received an error in IE with the original code. But after breaking tryIt into two functions, then count = 0 for IE. Evidently the extra function call was enough time to load and parse the file.

    It would be more interesting to run this test with a larger js file and with it 'online' instead of local.

  5. #5
    SitePoint Member
    Join Date
    Jan 2005
    Location
    melbourne
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Is there a neat way (rather than a busy wait) to poll for the Test object's availability? Breaking it up into two functions with the setTimeout works provided there isn't a whole chain of calls preceding (in the example) the call to tryIt

  6. #6
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Busy wait? I'm not sure what you mean. Normally I would not set it at 10ms, I did that just to watch the 'count' variable.

    setTimeout effectively allows you to "spawn a thread" - I think that's pretty neat

    Besides, it's the only way I know how to 'wait' in javascript

    Of course, you can always document.write a script element as the file loads, then the objects will be available after the onload event.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •