实现 JSONP

跨域Ajax有两种方式,<img src="out_url"/> 和 <sccript src="outside_url"></script>

JSONP使用的就是 script方式。

jsonp.js

代码
var jsonp = (function(window){
    
var document = window.document;
    
var extend = function(obj, attrs){
        
for(var name in attrs){
            obj[name] 
= attrs[name];
        }
    };

    
var Class={
        create: 
function(class_define){
            
var class_ = function(){};
            extend(class_, class_define);
            class_.create 
= function(attrs){
                
var obj = new class_();
                extend(obj, attrs);
                
if(obj.init){obj.init();}
                
return obj;
            };
            
return class_;
        }
    };

    
var is_ie = !!window.ActiveXObject;

    
var jsonp_imp=null;
    
var jsonp = function () {
        jsonp_imp.apply(
null, arguments);    
    };

    extend(jsonp, {
        guid:
0,
        requests:{},
        avail_tag:[],
        request_timeout:
5 //seconds
    });


    
var removeChildSafe = function(parent, node) {
        
for(var i=0, len=node.childNodes.length; i<len; ++i) {
            removeChildSafe(node, node.childNodes[i]);
        }
        parent.removeChild(node);
    };

    
var Request = Class.create({
        prototype:{
            remove:
function(){
                
var js = this.js;
                
if(is_ie) {    
                    
this.finished = 1;
                    
this.on_ready_state_change();
                    js.detachEvent(
"onreadystatechange"this.on_ready_state_change);
                    
this.js = null;
                } 
                removeChildSafe(js.parentNode, js);    
                js 
= null;
                
delete jsonp.requests[this.id];
            },
            on_complete:
function(){
                
if(this.success) {
                    
this.success();
                    
this.success = null;
                }
            },
            on_timeout:
function(){
                
var state = this.js.readyState;
                
if( state != 'complete' &&  state != 'loaded' && this.failed) {
                    
this.failed();
                    
this.failed = null;
                }
                state 
= null;
                
this.remove();
            },
            init:
function(){
                
var request = this;
                
if(is_ie) {
                    request.on_ready_state_change 
= function(){
                        
if(request.finished) {
                            request 
= null;
                            
return;
                        }
                        
if(request.js.readyState=='complete' || request.js.readyState=='loaded') {
                            request.on_complete();
                        }
                    };
                    
this.js.attachEvent("onreadystatechange", request.on_ready_state_change);
                } 
else {
                    
this.js.onload = function(){ 
                        request.on_complete();
                    };
                }
                setTimeout(
function(){request.on_timeout();}, request.timeout);
            }
        }
    });

    
var head = document.getElementsByTagName('head')[0];
    jsonp_imp 
= function(url, charset, timeout, failed, success) {
        
var js = document.createElement('script');
        head.appendChild(js);
        
if(!charset) {charset = 'utf-8';}
        
var id = jsonp.guid++;
        
if(!timeout) {timeout = jsonp.request_timeout*1000;}
        
var now = new Date();
        
var request = Request.create({
                    id: id,
                    url: url,
                    charset: charset, 
                    failed: failed, 
                    success: success,
                    js: js, 
                    stat_time: now,
                    timeout: timeout
        });
        jsonp.requests[id] 
= request;
        js.charset 
= charset;
        js.src 
= url;
        
return id;
    };
    
    
return jsonp;
})(window);


测试代码:

jsonp("http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.js",
    null,
    function(){alert("timeout");},  
    function(){alert("load ok");}
);


IE6内存泄漏测试:

incr.js

incr();


test_ie6.html

<html>
<head>
<script src='jsonp.js'></script>
</head>
<body>
<div id="t">ok</div>
<script defer="defer">
    
var i = 0;
    
var incr = function(){ 
        
++i;
        document.getElementById(
't').innerHTML=i;
    };
    setInterval(
function(){jsonp("incr.js");},1000);
</script>
</body>
</html>


IE6下内存泄露,还没有找到比较好方法,不过泄露的比较少1K次请求1M左右。

Jquery等很多库在IE6下都有泄漏。IE6真的应该淘汰了。

 

posted @ 2010-11-04 20:28 napoleon_liu 阅读(...) 评论(...) 编辑 收藏