如何等待动态包含的 javascript 文件正确加载?

how to wait until a dynamically included javascript file is properly loaded?

我使用包含函数来动态包含 javascript files/headers/libraries。

问题是它似乎以多线程方式加载文件(在 Chrome v102 上测试)并且 js 文件尚未加载时之后我立即使用功能。

示例jQuery:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf8"/>
        <script type="text/javascript">
            var include_once = function(url) {
                /*
                [additional code to check if 'url' was already included]
                */
                var script = document.createElement("script");
                script.type = "text/javascript";
                script.src = url;
                document.head.appendChild(script);
            }
            
            include_once("https://code.jquery.com/jquery-3.6.0.min.js");
        </script>
    </head>
    <body>
        <script type="text/javascript">
            /*
            ok if I wait 'long enough' but is arbitrary
            */
            setTimeout(function(){
                $(document).ready(function(){
                    console.log("ready (timeout)");
                });
            }, 10);
            
            /*
            how to wait until window.$ is defined?
            */
            $(document).ready(function(){
                console.log("ready");
            });
        </script>
    </body>
</html>

此代码可能会给您一个 $ is not defined 错误,并且 ready (timeout) 将被记录到控制台。

如何让我的脚本等到 window.$ !== undefined 这里?

我尝试了 while(window.$ === undefined) {} 但它完全阻止了脚本并且 $ 从未被定义。

您可以通过在第一个脚本上创建承诺然后在第二个脚本上检查承诺是否已解决来承诺加载过程。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf8"/>
        <script type="text/javascript">
            var isLoaded = new Promise((res,rej) => {
              function include_once(url) {
                  /*
                  [additional code to check if 'url' was already included]
                  */
                  var script = document.createElement("script");
                  script.type = "text/javascript";
                  script.onload = () => res()
                  script.onerror = () => rej()
                  script.src = url;
                  document.head.appendChild(script);
              }
              include_once("https://code.jquery.com/jquery-3.6.0.min.js");
          })
          
        </script>
    </head>
    <body>
        <script type="text/javascript">
            isLoaded.then(() => {
              $(document).ready(function(){
                console.log("ready");
            });
            })
        </script>
    </body>
</html>