什么是一个好方法来尝试加载托管的jQuery在谷歌(或其他谷歌托管库),但加载我的jQuery副本,如果谷歌尝试失败?
我不是说谷歌很古怪。在某些情况下,谷歌副本会被屏蔽(例如,显然在伊朗)。
我是否会设置一个计时器并检查jQuery对象?
两份拷贝都通过的危险是什么?
并不是真的在寻找像“只用谷歌”或“只用你自己的”这样的答案。我理解这些论点。我还知道用户可能缓存了谷歌版本。我在考虑云计算的后备方案。
编辑:这部分增加了…
因为谷歌建议使用谷歌。加载加载ajax库,它执行回调时,我想知道这是否是序列化这个问题的关键。
我知道这听起来有点疯狂。我只是想弄清楚它是否能以一种可靠的方式完成。
更新:jQuery现在托管在微软的CDN上。
http://www.asp.net/ajax/cdn/
我做了一个Gist,如果还没有加载jQuery,它应该动态加载,如果源代码失败,它将继续执行回退(从许多答案拼接在一起):https://gist.github.com/tigerhawkvok/9673154
请注意,我计划保持更新主旨,但不是这个答案,因为它是值得的!
/* See https://gist.github.com/tigerhawkvok/9673154 for the latest version */
function cascadeJQLoad(i) { // Use alternate CDNs where appropriate to load jQuery
if (typeof(i) != "number") i = 0;
// the actual paths to your jQuery CDNs
var jq_paths = [
"ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js",
"ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js"
];
// Paths to your libraries that require jQuery
var dependent_libraries = [
"js/c.js"
];
if (window.jQuery === undefined && i < jq_paths.length) {
i++;
loadJQ(jq_paths[i], i, dependent_libraries);
}
if (window.jQuery === undefined && i == jq_paths.length) {
// jQuery failed to load
// Insert your handler here
}
}
/***
* You shouldn't have to modify anything below here
***/
function loadJQ(jq_path, i, libs) { //load jQuery if it isn't already
if (typeof(jq_path) == "undefined") return false;
if (typeof(i) != "number") i = 1;
var loadNextJQ = function() {
var src = 'https:' == location.protocol ? 'https' : 'http';
var script_url = src + '://' + jq_path;
loadJS(script_url, function() {
if (window.jQuery === undefined) cascadeJQLoad(i);
});
}
window.onload = function() {
if (window.jQuery === undefined) loadNextJQ();
else {
// Load libraries that rely on jQuery
if (typeof(libs) == "object") {
$.each(libs, function() {
loadJS(this.toString());
});
}
}
}
if (i > 0) loadNextJQ();
}
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
try {
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
} catch (e) {
// do nothing, no callback function passed
}
};
s.onerror = function() {
try {
if (!callback.done) {
callback.done = true;
callback();
}
} catch (e) {
// do nothing, no callback function passed
}
}
document.getElementsByTagName('head')[0].appendChild(s);
}
/*
* The part that actually calls above
*/
if (window.readyState) { //older microsoft browsers
window.onreadystatechange = function() {
if (this.readyState == 'complete' || this.readyState == 'loaded') {
cascadeJQLoad();
}
}
} else { //modern browsers
cascadeJQLoad();
}
虽然编写document.write("<script></script>")对于jQuery来说似乎更容易退出,但Chrome在这种情况下给出了验证错误。所以我更喜欢打破“剧本”这个词。所以它变得像上面一样安全。
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.1.min.js"></script>
<script>if (typeof jQuery === "undefined") {
window.jqFallback = true;
document.write("<scr"+"ipt src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js'></scr"+"ipt>");
} </script>
对于长期的问题,最好记录JQuery的回退。在上面的代码中,如果第一个CDN不可用,则从另一个CDN加载JQuery。但是你可能想要知道错误的CDN并永久删除它。(这种情况是非常特殊的情况)此外,最好记录回退问题。所以你可以用AJAX发送错误案例。因为JQuery没有定义,所以对于AJAX请求应该使用普通的javascript。
<script type="text/javascript">
if (typeof jQuery === 'undefined' || window.jqFallback == true) {
// XMLHttpRequest for IE7+, Firefox, Chrome, Opera, Safari
// ActiveXObject for IE6, IE5
var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
var url = window.jqFallback == true ? "/yourUrl/" : "/yourUrl2/";
xmlhttp.open("POST", url, true);
xmlhttp.send();
}
</script>
这里有一些很好的解决方案,但我想在本地文件方面更进一步。
在谷歌确实失败的情况下,它应该加载一个本地源,但服务器上的物理文件不一定是最佳选择。之所以提出这一点,是因为我目前正在实现相同的解决方案,只是希望返回到由数据源生成的本地文件。
我这样做的原因是,当涉及到跟踪我从谷歌加载的内容与我在本地服务器上的内容时,我想有一些想法。如果我想要更改版本,我将希望保持我的本地副本与我试图从谷歌加载的内容同步。在有许多开发人员的环境中,我认为最好的方法是自动化这个过程,这样所有人所要做的就是更改配置文件中的版本号。
以下是我提出的理论上可行的解决方案:
In an application configuration file, I'll store 3 things: absolute URL for the library, the URL for the JavaScript API, and the version number
Write a class which gets the file contents of the library itself (gets the URL from app config), stores it in my datasource with the name and version number
Write a handler which pulls my local file out of the db and caches the file until the version number changes.
If it does change (in my app config), my class will pull the file contents based on the version number, save it as a new record in my datasource, then the handler will kick in and serve up the new version.
理论上,如果我的代码写得正确,我所需要做的就是改变我的应用程序配置中的版本号,然后viola!你有一个自动的备用解决方案,你不必在服务器上维护物理文件。
大家怎么想?也许这有点过分了,但这可能是维护AJAX库的一种优雅方法。
橡子
如果你的网站上嵌入了modernizr.js,你可以使用内置的yepnope.js来异步加载你的脚本——其中包括jQuery(带备份)。
Modernizr.load([{
load : '//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'
},{
test : window.jQuery,
nope : 'path/to/local/jquery-1.7.2.min.js',
both : ['myscript.js', 'another-script.js'],
complete : function () {
MyApp.init();
}
}]);
这将从Google-cdn加载jQuery。然后检查jQuery是否加载成功。如果不是("nope"),则加载本地版本。同时也加载了您的个人脚本——“both”表示加载过程的初始化独立于测试的结果。
当所有加载过程完成时,执行一个函数,在这种情况下为'MyApp.init'。
我个人更喜欢这种异步脚本加载方式。由于我在构建网站时依赖modernizr提供的功能测试,所以我将它嵌入到网站中。所以实际上没有开销。