如何知道动态创建的脚本标签已执行?

时间:2014-09-05 14:59:58

标签: javascript createelement script-tag

我正在动态创建脚本标记:

var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.charset = 'utf-8';
script.defer = true;
script.async = true;
script.text = 'some my javascript content here';
head.appendChild(script);

script.onload = function () {
    // this never get fired..
    debugger;
}

如何在其他代码块中执行脚本时收到通知?也许有些事情?

谢谢!

7 个答案:

答案 0 :(得分:9)

我能够通过向脚本添加ID来实现此功能,然后在JS中,手动触发该DOM元素上的load事件。仅在Chrome中进行测试,根据MDN)在旧IE中会出现问题。

var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.charset = 'utf-8';
script.id = 'testing';
script.defer = true;
script.async = true;
script.onload = function () {
    console.log('The script is loaded');
}
script.text = ["console.log('This is from the script');",
               "var script = document.getElementById('testing');",
               "var event = new UIEvent('load');",
               "script.dispatchEvent(event);"].join('');
head.appendChild(script);

Fiddle

答案 1 :(得分:1)

在现代浏览器中,您可以使用Mutation Observer来检测元素中的更改 - 在这种情况下为head。像这样:

observer = new MutationObserver(function (m) {
    // This will be fired
});
observer.observe(document.head, {childList: true});

不幸的是,这在IE< 11,但似乎在IE中触发onload,因此您可以将其用于IE。

A live demo at jsFiddle

答案 2 :(得分:0)

如果脚本被附加到DOM,则代码每100毫秒检查一次。您可以在应用程序中的任何位置使用它,而无需事件侦听器和调度事件。 同样,您可以看到一个时间间隔,如果脚本没有在您设置的时间间隔内追加,代码将在该时间间隔内抛出错误。

const waitForScriptToLoad = (scriptName, checkTimeMs, timeOutMs) => {
  let elapsedTime = 0;
  return new Promise((resolve, reject) => {
    setTimeout(x => reject('script: ' + scriptName + ' Timed out!')
      , timeOutMs)
    const time = setInterval(() => {
      elapsedTime += checkTimeMs;
      if (document.body.innerHTML.indexOf(scriptName) > -1) {
        resolve(
          {
            response: 'script: ' + scriptName + ' found!',
            time: (elapsedTime / 1000).toFixed(2) + 's'
          });
        clearInterval(time);
      }
    }, checkTimeMs)
  })
}

waitForScriptToLoad('script_name.js', 100, 20000)
  .then(res => console.log(res))
  .catch(err => console.log(err))

答案 3 :(得分:-1)

在设置脚本源之前,需要定义onload函数。但是,正如Teemu告诉我的那样,由于您是通过text属性编写javascript,因此onload事件永远不会触发。您最好的选择是拥有一个外部js文件并通过src属性加载它。

订单应该是:

  
      
  • 将脚本元素附加到DOM
  •   
  • 定义onload函数
  •   
  • 定义src
  •   
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.charset = 'utf-8';
script.defer = true;
script.async = true;
head.appendChild(script);
script.onload = function () {
    // this never get fired..
    debugger;
}
script.src = 'scriptName.js';

然后你的onload事件应该触发,你可以在函数中插入console.log("script has loaded!");语句。

答案 4 :(得分:-1)

将代码解压缩到.js文件。

script.src = 'yourjs.js';添加到脚本中。

将脚本添加到DOM时,会立即执行.js文件。

if(console){console.debug('helloworld.');}的ontop上添加yourjs.js,您会看到该消息。

答案 5 :(得分:-1)

另一种解决方案(不使用onloadsrc

window.onload = function(){

    var script = document.createElement('SCRIPT'),
        content = 'console.debug("Hello Kitty");'; // or console.log

    script.type = 'text/javascript';

    try {
      script.appendChild(document.createTextNode(content));
    } catch (e) {
      script.text = content;
    } finally {
      document.getElementsByTagName("HEAD")[0].appendChild(script);
    }
};

Working demo(在IE,FF,Chrome和Opera上测试过)

答案 6 :(得分:-2)

出于测试目的,您始终可以添加对alert()函数的调用。但是,在查看您的代码后,我不确定我是否在其中看到实际调用该函数的任何内容。那" onload"在执行appendChild()之前,可能应该将事件处理程序添加到动态创建部分。

我一段时间写了一些代码来做一些动态脚本创建,它运行正常。我的代码有两个主要功能,一个用于创建脚本(一堆脚本),从" .js"中加载数据。文件和另一个调用这些脚本中的函数的顺序,由它们的名称决定(使用" eval()"函数)。你的函数没有我能看到的任何名字......我知道很多人都不喜欢使用eval()函数,但只要它被调用的唯一东西就是你在其中写的东西整个,应该没事。

此代码允许BROWSER而不是Web服务器动态创建可点击链接项的菜单(每个可点击链接看起来像普通超链接,但实际上是JavaScript构造,浏览器必须为其启用JavaScript链接工作 - 但它必须启用JavaScript才能创建菜单,所以没问题!):

 var F00, F01, F02, F03, F04, F05, F06, F07, F08, F09,
     F10, F11, F12, F13, F14, F15, F16, F17, F18, F19;
 var dat = new Array();
 var form, script, str, st2, tmp, tmp2, dtno, indx, unde;

 function initialize()
 { window.name="MyMenu";
   form = document.getElementById('MENU');
   for(indx=0; indx<20; indx++)
   { str = "0" + indx;
     tmp = str.length - 2;
     str = str.substr(tmp);
     script = document.createElement('script');
     script.type = 'text/javascript';
     script.src = str + ".js";
     form.appendChild(script);
   }
   window.setTimeout("BuildMenu();", 1000); //delay is necessary;
      // scripts are actually only loaded after the function ends,
      // and you need to allow time for it to finish
      // before calling the functions in those scripts.
   return;
 }

请注意,此代码已准备好处理20个菜单项,即使您目前只有5个项目可以在菜单上使用。如果20个最大值中的一些&#34; .js&#34;以上功能不会崩溃。文件不存在。

 function BuildMenu()
 { dtno = 0;
   for(indx=0; indx<20; indx++)
   { str = "0" + indx;
     tmp = str.length - 2;
     str = "F" + str.substr(tmp);
     tmp = eval(str);
     if(tmp != unde)  //no value is assigned to 'unde'; it is undefined;
                      //this is a valid way to find out
                      //whether or not a ".js" script existed/was-loaded.
       dat[dtno++] = eval(str + "()");
   }
   dat.sort();
   for(indx=0; indx<dtno; indx++)
   { str = "0" + indx;
     tmp = str.length - 2;
     str = "W" + str.substr(tmp);
     tmp = document.getElementById(str);
     tmp.innerHTML = "<a onclick=\"window.open('" + dat[indx][1] + "', 'MyMenu');\" style=\"color:#0000ff;text-decoration:underline;cursor:pointer;\">" + dat[indx][0] + "</a> " + dat[indx][2] + "<br />";
   }
   return;
 }

在网页的HTML代码中,有以下内容:

 <body onload="initialize();>
 <br />
 <form id="MENU" action="" onsubmit="return false;">
 <span id="W00">&nbsp;</span>
 <span id="W01">&nbsp;</span>
 <span id="W02">&nbsp;</span>
 <span id="W03">&nbsp;</span>
 <span id="W04">&nbsp;</span>
 <span id="W05">&nbsp;</span>
 <span id="W06">&nbsp;</span>
 <span id="W07">&nbsp;</span>
 <span id="W08">&nbsp;</span>
 <span id="W09">&nbsp;</span>
 <span id="W10">&nbsp;</span>
 <span id="W11">&nbsp;</span>
 <span id="W12">&nbsp;</span>
 <span id="W13">&nbsp;</span>
 <span id="W14">&nbsp;</span>
 <span id="W15">&nbsp;</span>
 <span id="W16">&nbsp;</span>
 <span id="W17">&nbsp;</span>
 <span id="W18">&nbsp;</span>
 <span id="W19">&nbsp;</span>
 </form>

以下是&#34; 00.js&#34;的一些示例代码。文件:

 <!--
 function F00()
 { return ["Menu Item Alpha", "./Alpha.htm", "Select Web Page Alpha"];
 }
 -->

注意该函数只返回3个数组元素(字符串)。 BuildMenu()函数在构建网页上的菜单时使用这些字符串,部分是通过修改span元素的innerHTML。