繁体   English   中英

从跨域脚本中提取对象的优雅方法

[英]Elegant way of extracting an object from a cross-domain script

为了加载一些geojson数据,我需要在外部域上获取脚本,例如http://www.stat.ucla.edu/~jeroen/files/la_county_simplified.min.json 我无法控制此脚本的内容; 我只知道url,以及我感兴趣的脚本中定义的对象的名称。脚本的虚拟版本如下:

var my_data = {"foo" : 123, "bar" : 456}

现在在我的应用程序中,我想从其URL动态加载my_data对象。 因为它是跨域的,所以我不能使用ajax。 它也不是jsonp ,因为我的脚本定义了一个对象,而不是一个函数。 一种方法是将其简单地作为<script>插入当前文档的开头。 但是,我想避免可能的副作用。

什么是更清洁的解决方案? 我当时正在考虑创建<iframe> ,然后在<iframe>插入<script>标记,并在iframe加载后提取对象。 但是,我不确定这是否是一种可在跨浏览器中使用的可靠方法(尤其是在将脚本加载到iframe中后,绑定一个回调以提取对象)。

是否有一些库或标准解决方案可将脚本加载到干净页面中,并将特定对象上的副本提取到主页上? 我已经对jQuery有依赖关系,这样就可以了。

如果您打算做这种纯客户端操作,并且无法格式化数据,则可以使用带有twist的 JSONP。 我们没有修改数据以适合回调,而是重新修改了加载器以采用该数据。

我们监听脚本的onload 脚本加载后,变量现在应该在全局范围内,并且我们执行回调,该回调将全局变量传递到我们的回调中。

//your script loader
function loadData(url,varName,callback){

  var script = document.createElement('script');
  document.getElementsByTagName('head')[0].appendChild(script);

  //when the script loads, we pass in `window.my_data`
  script.onload = function(){
    callback.call(this,window[varName]);
  };
  script.src = url;

}

//using it
loadData('http://example.com/somefile.js','my_data',function(data){
  //executes when script is loaded, where data is `my_data`
});

这种方法的缺点是,每次加载脚本时,都将其加载到全局范围中,可能会发生冲突。

没有其他方法可以解决,因为您必须克服必须将原始脚本加载到新脚本标签中的原始策略,JSONP也可以使用这种方法,但jquery会为您隐藏它。

如果该站点没有cors头,则该站点或该站点都具有cors头,这是您可以如何加载数据(不使用jsonp,因为它不是jsonp格式):

function loadJS(url){
  var s=document.createElement("script");
  s.src=url;
  $(s).on("load",function(){
    console.log("var abvailable");//do something with the variable here
    $(s).remove();
  });
  document.head.appendChild(s);
}
loadJS("http://code.jquery.com/jquery-1.9.1.min.js");

iframe方法应该可以正常工作:

  • 创建一个iframe
  • 注入指向文件的脚本标签
  • 在脚本加载时,检索对象

我能想到的唯一跨浏览器问题是,您将需要在现代浏览器中使用addEventListener并在旧IE中使用attachEvent。

这是将iframe用作沙箱的标准用法-如果我理解正确,那么您担心与全局变量名称可能会发生冲突。

[更新]要解决您的一些意见,下面是一些跨浏​​览器的代码:

要添加事件监听器:

function addEvent(element,event,fn,capture){
// capture defaults to false if omitted
if (element.addEventListener) {element.addEventListener(event,fn,(capture||false));}
// else for old IE
else {element.attachEvent('on'+event,fn);}
};

要访问iframe文档,请执行以下操作:

function iframeDocument(ifr){
var doc=ifr.contentWindow||ifr.contentDocument;
if (doc.document) doc=doc.document;
return doc;
};

如果使用jQuery, .on("load")$(ifr).contents()将解决这些跨浏览器的兼容性问题。

JSON-P是从远程域加载JavaScript的一种方式。

JavaScript的返回格式是调用以响应数据为参数的函数。

someGlobalFunctionName({/* your response data */});

function someGlobalFunctionName(data) { /* do something with data */ }

由于数据包含在对象中并传递给函数,因此除了全局函数本身之外,没有其他全局泄漏,这是不可避免的。

更多信息: http//json-p.org/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM