• 跨域的异步请求四


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

  • 相关阅读:
    技巧:在Silverlight中如何访问外部xap文件中UserControl
    Silverlight:代码隐藏和分部类
    silverlight 反射调用WebService
    [推荐]Silverlight 2 开发者海报
    轻松建立Silverlight开发环境
    windows 卸载IE8还原IE7的方法
    如何:访问双工服务
    技巧:在Silverlight 2应用程序中切换用户控件
    如何减少silverlight XAP包的尺寸
    Silverlight:应用程序和编程模型
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1953087.html
Copyright © 2020-2023  润新知