跨域的异步请求四
本文将一种崭新的为JSONP添加onerror事件的跨浏览器解决方案。由于ie6~8及opera的script标签不支持onerror事件,因此一般的类库(包括jquery,及其他我所看到的库)也无法处理它们的JSONP的onerror回调(下称负向回调)。难道就没有办法吗?经笔者发现,JSONP的回调函数(下称正向回调)总是在script的onload事件(IE为onreadystatechange)之前就被调用了。因此我们在正向回调执行之时,为script标签添加一个属性,然后待到onload发生时,再检测有没有这个属性就可以判定是否请求成功,没有成功当然就调用我们的负向回调了!
//2011.2.13 by 司徒正美
;;;(function(WIN,DOM,undefined){
var _dom = WIN.dom,
slice = Array.prototype.slice,
dom = {
mix : function(target, source ,override) {
var i, ride = (override === void 0) || override;
for (i in source) {
if (ride || !(i in target)) {
target[i] = source[i];
}
}
return target;
},
noConflict: function( ) {//防止命名冲突,请先行引用其他库再引用本框架
WIN.dom = _dom;//这是别人的
return dom;//请赋以其一个命名空间
},
jsonp:function(){
var self = arguments.callee,
args = self.args(arguments),
url = args[0],
data = args[1],
callback = args[2],
errback = args[3],
jsonpkey = args[4],
jsonpname = "callback"+1*new Date,
jsonpval = "dom.jsonp."+jsonpname,
add = /\?/.test( url ) ? "&" : "?",
script = DOM.createElement("script"),
query =[];
data[jsonpkey] = jsonpval
self[jsonpname] = function(json){
script.jsonp = 1;
callback(json);
}
for(var i in data){
query.push(i +"="+data[i])
}
url = url + add + query.join("&")
script.src = url;
script.onload = script.onreadystatechange = function(){
if( -[1,] || /loaded|complete/i.test(this.readyState)){
self.removeScript(this,errback,jsonpname);
}
}
script.onerror = function(){
self.removeScript(this,errback,jsonpname);
}
var head = DOM.getElementsByTagName("head")[0];
head.appendChild(script);
}
}
dom.mix(dom.jsonp, {
args : function(obj){
var array = slice.call(obj)
if(array.length === 1){
obj = array[0]
array = [obj.url,obj.data,obj.callback,obj.errback,obj.jsonpkey]
}
if(typeof array[1] === "function"){
array.splice(1,0,{});//让正向回调回到其正确位置
}
if(typeof array[3] !== "function"){
array.splice(3,0,function(){});//让负向回调回到其正确位置
}
array[4] = array[4] || "jsoncallback";
return array;
},
removeScript: function(script,error,jsonpname){
if(typeof script.jsonp === "undefined" ){
error();
}
if (script.clearAttributes) {
script.clearAttributes();
} else {
script.onload = script.onreadystatechange = script.onerror = null;
}
script.parentNode.removeChild(script);
delete this[jsonpname];
}
});
window.dom = dom;
})(this,this.document);
dom.jsonp.args会对dom.jsonp的参数进行了重写,因此dom.jsonp支持多种传参方式:
dom.jsonp(url,args,callback,errback,jsonpkey)
dom.jsonp(url,callback,errback,jsonpkey)
dom.jsonp(url,callback,jsonpkey)
dom.jsonp(url,callback)
dom.jsonp({
url:'',
callback:function(){}
//其他.....
})
使用示例:
dom.jsonp("http://del.icio.us/feeds/json/fans/stomita",function(json){alert(json)},"callback");
下面例子请用firebug查看请求状态与结果!
机器瞎学/数据掩埋/模式混淆/人工智障/深度遗忘/神经掉线/计算机幻觉/专注单身二十五年
浙公网安备 33010602011771号