document.createElement(“script”) synchronously

前端 未结 11 2086
执念已碎
执念已碎 2020-11-22 12:56

Is it possible to call in a .js file synchronously and then use it immediately afterward?



        
相关标签:
11条回答
  • 2020-11-22 13:55

    The answers above pointed me in the right direction. Here is a generic version of what I got working:

      var script = document.createElement('script');
      script.src = 'http://' + location.hostname + '/module';
      script.addEventListener('load', postLoadFunction);
      document.head.appendChild(script);
    
      function postLoadFunction() {
         // add module dependent code here
      }      
    
    0 讨论(0)
  • 2020-11-22 13:55

    This looks like a decent overview of dynamic script loading: http://unixpapa.com/js/dyna.html

    0 讨论(0)
  • 2020-11-22 13:57

    You can create your <script> element with an "onload" handler, and that will be called when the script has been loaded and evaluated by the browser.

    var script = document.createElement('script');
    script.onload = function() {
      alert("Script loaded and ready");
    };
    script.src = "http://whatever.com/the/script.js";
    document.getElementsByTagName('head')[0].appendChild(script);
    

    You can't do it synchronously.

    edit — it's been pointed out that, true to form, IE doesn't fire a "load" event on <script> tags being loaded/evaluated. Thus I suppose the next thing to do would be to fetch the script with an XMLHttpRequest and then eval() it yourself. (Or, I suppose, stuff the text into a <script> tag you add; the execution environment of eval() is affected by the local scope, so it won't necessarily do what you want it to do.)

    editAs of early 2013, I'd strongly advise looking into a more robust script loading tool like Requirejs. There are a lot of special cases to worry about. For really simple situations, there's yepnope, which is now built into Modernizr.

    0 讨论(0)
  • 2020-11-22 13:57

    This isn't pretty, but it works:

    <script type="text/javascript">
      document.write('<script type="text/javascript" src="other.js"></script>');
    </script>
    
    <script type="text/javascript">
      functionFromOther();
    </script>
    

    Or

    <script type="text/javascript">
      document.write('<script type="text/javascript" src="other.js"></script>');
      window.onload = function() {
        functionFromOther();
      };
    </script>
    

    The script must be included either in a separate <script> tag or before window.onload().

    This will not work:

    <script type="text/javascript">
      document.write('<script type="text/javascript" src="other.js"></script>');
      functionFromOther(); // Error
    </script>
    

    The same can be done with creating a node, as Pointy did, but only in FF. You have no guarantee when the script will be ready in other browsers.

    Being an XML Purist I really hate this. But it does work predictably. You could easily wrap those ugly document.write()s so you don't have to look at them. You could even do tests and create a node and append it then fall back on document.write().

    0 讨论(0)
  • 2020-11-22 14:00

    This works for modern 'evergreen' browsers that support async/await and fetch.

    This example is simplified, without error handling, to show the basic principals at work.

    // This is a modern JS dependency fetcher - a "webpack" for the browser
    const addDependentScripts = async function( scriptsToAdd ) {
    
      // Create an empty script element
      const s=document.createElement('script')
    
      // Fetch each script in turn, waiting until the source has arrived
      // before continuing to fetch the next.
      for ( var i = 0; i < scriptsToAdd.length; i++ ) {
        let r = await fetch( scriptsToAdd[i] )
    
        // Here we append the incoming javascript text to our script element.
        s.text += await r.text()
      }
    
      // Finally, add our new script element to the page. It's
      // during this operation that the new bundle of JS code 'goes live'.
      document.querySelector('body').appendChild(s)
    }
    
    // call our browser "webpack" bundler
    addDependentScripts( [
      'https://code.jquery.com/jquery-3.5.1.slim.min.js',
      'https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js'
    ] )
    
    0 讨论(0)
提交回复
热议问题