添加script
节点应该可以正常工作。因为这些脚本将与添加它们的代码异步执行,所以您需要给它们一个回调来调用以按顺序执行下一件事。例如:
if (window.localStorage) {
// Load the local storage stuff; once loaded, it'll call
// `doTheNextThing`
var script = document.createElement('script');
script.type = "text/javascript";
script.src = /* ... the URL of the script ... */;
document.body.appendChild(script); // Or append it to `head`, doesn't matter
// and `document.body` is convenient
}
else {
// Skip loading it
setTimeout(doTheNextThing, 10);
}
function doTheNextThing() {
// ...
}
...您正在加载的动态脚本在加载后localStorage
调用doTheNextThing
的地方 - 因此,在有 的情况下localStorage
,动态加载的脚本会调用doTheNextThing
,但在没有的情况下,上面的代码会调用。请注意,我是故意从上面的代码中进行调用的异步(通过setTimeout
):使其始终异步,无论它是如何被调用的,这样可以减少丢失错误的几率(例如,添加一些依赖于它被同步调用然后忘记测试的东西IE 上的小改动)。
更新:以上假设您可以控制正在加载的脚本,但您已经澄清您不是。在这种情况下,您需要做的是一次加载一个脚本并轮询它们提供的功能(通常是对象上的window
属性,例如window.jQuery
),如下所示(未经测试):
// Load the script designated by `src`, poll for the appearance
// of the symbol `name` on the `window` object. When it shows
// up, call `callback`. Timeout if the timeout is reached.
function loadAndWait(src, name, timeout, callback) {
var stop, script;
// Do nothing if the symbol is already defined
if (window[name]) {
setTimeout(function() {
callback("preexisting");
}, 10);
}
else {
// Load the script
script = document.createElement('script');
script.type = "text/javascript";
script.src = src;
document.body.appendChild(script);
// Remember when we should stop
stop = new Date().getTime() + timeout;
// Start polling, long-ish initial interval
setTimeout(poll, 150);
}
function poll() {
if (window[name]) {
// Got it
callback("loaded");
}
else if (new Date().getTime() > stop) {
// Time out
callback("timeout");
}
else {
// Keep waiting, shorter interval if desired
setTimeout(poll, 75);
}
}
}
...您将像这样用于 jQuery 加载:
loadAndWait(
"http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js",
"jQuery",
10000, // ten seconds or whatever
function(result) {
// ...do the next one if result !== "timeout"
}
);
您可以loadAndWait
在每个先前调用的回调中嵌套调用,也可以使用数组和计数器:
loadThese(
[
{ src: "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js",
symbol: "jQuery"
},
{
src: "http://the-next-one",
symbol: "nextSymbol"
}
],
doTheNextThing
);
function loadThese(scripts, callback) {
var index = 0;
run("okay");
function run(result) {
var entry;
if (result === "timeout") {
callback(result);
}
else if (index < scripts.length) {
entry = scripts[index++];
loadAndWait(entry.src, entry.symbol, 10000, run);
}
else {
callback("loaded");
}
}
}
在那里,loadThese
设置一个循环来run
依次加载每个脚本。
以上所有内容都是现成的,可能会被收紧和防弹,但你明白了。
题外话,但我的问题是:真的有这么多的代码,对于不能使用它来加载它的浏览器来说是个问题吗?除非文件变得更大,否则对于使用高级浏览器的用户来说,您实际上会减慢您的网站速度,而不会从其他人那里获得任何东西。在一定大小以下,连接到服务器以检索脚本的开销与传输脚本一样大。额外的东西是 50k 的代码吗?我会做一些基准测试来测试它是否真的有必要......也许是(也许你已经拥有了!),但值得一提......
离题更新localStorage
:在您更新的问题中,您列出了五个单独的脚本,如果支持,您将下载这些脚本。即使假设您从各种 CDN 获得所有五个,这也是许多单独的脚本请求(无论是按常规方式完成还是按上述方式完成),每个都必须一次处理一个。这是一个等待发生的页面加载性能问题。尽管(可能)失去了 CDN 和现有缓存的好处,但您可能会考虑抓取所有这些脚本,将它们组合起来,并将组合版本托管在一个文件中。请参阅YUI 性能“规则”中的“最小化 HTTP 请求” (我更喜欢术语“指南”,但无论如何)。它还将简化您的动态加载。