Ruby's Louvre

每天学习一点点算法

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

跨域的异步请求四

本文将一种崭新的为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查看请求状态与结果!

如果您觉得此文有帮助,可以打赏点钱给我支付宝1669866773@qq.com ,或扫描二维码

posted on   司徒正美  阅读(5284)  评论(5编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2010-02-13 kangax 的javascript谜题
点击右上角即可分享
微信分享提示