1. 程式人生 > >指令碼繫結回撥增強版:備用url可以失敗重試

指令碼繫結回撥增強版:備用url可以失敗重試

4年前寫過一篇《指令碼繫結回撥》 http://www.blogjava.net/emu/articles/129240.html 進行了一些有趣的嘗試,這些嘗試現在在一些web產品中已經應用了好幾年了。這兩年隨著海外使用者的增多,使用者情況的複雜化,我們的服務部署也開始複雜化了,有一些使用者訪問A域名失敗,訪問B域名就可能很暢順,另一些使用者則相反。而且很多時候這並不是gslb這樣的排程可以及時檢測到和快速調整的,不由得想想,能不能進行失敗重試呢?其實也很簡單把4年前的程式碼改了一改,做了一個原理性的實驗:

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
var isIE = !!window.ActiveXObject;
var useFragment=false;
function loadjs(url,callback,errcallback,url2,url3){
    if(isIE){
        if(useFragment){
           var df = document.createDocumentFragment();    
            df.visitCountCallBack = function(data){
                s.onreadystatechange=null;
                df=null;
                callback(data);
            }
            var s = df.createElement("SCRIPT");
            df.appendChild(s);
            s.onreadystatechange=function (ec,cb,u2,u3){
                return function(){
                    if(s.readyState=="loaded") {
                        s.onreadystatechange=null;
                        df=null;
                        if(!u2){
                            ec();
                        }else{
                            loadjs(u2,cb,ec,u3)
                        }
                    }
                }
            }(errcallback,callback,url2,url3)
            s.src = url;
        }else{
            var i=new ActiveXObject("htmlfile");
            i.open();
            i.parentWindow.visitCountCallBack=function(i){
                return function(d){
                    i.parentWindow.errcallback=null;
                    i=null;
                    callback(d);
                }
            }(i);
            i.parentWindow.errcallback=function(ec,cb,u2,u3){
                return function(){
                    i.parentWindow.errcallback=null;
                    i=null;
                    if(!u2){
                        ec();
                    }else{
                        loadjs(u2,cb,ec,u3)
                    }
                }
            }(errcallback,callback,url2,url3)
            i.write("<script src=\""+url+"\"><\/script><script defer>setTimeout(\"errcallback()\",0)<\/script>")
            if(i)i.close();//如果資料被cache,執行到這一行的時候有可能回撥已經完成,視窗已經關閉。
        }
    }else{
        var i = document.createElement("IFRAME");    
        i.style.display="none";
        i.callback=function(o){
            callback(o);
            i.contentWindow.callback=null;
            i.src="about:blank"
            i.parentNode.removeChild(i);
            i = null;
        };
        i.errcallback = function(ec,cb,u2,u3){
            return function(){
                    if(!u2){
                        ec();
                    }else{
                        loadjs(u2,cb,ec,u3)
                    }
            }
        }(errcallback,callback,url2,url3);
        i.src="javascript:\"<script>function visitCountCallBack(data){frameElement.callback(data)};<\/script><script src='"+url+"'><\/script><script>setTimeout('frameElement.errcallback()',0)<\/script>\"";
        document.body.appendChild(i);
    }
}

function init(){
    var spans = document.getElementsByTagName("span");
    for(var i=0;i<spans.length;i++){
        var id = spans[i].id;
        var url = "http://g.qzone.qq.com/fcg-bin/cgi_emotion_list.fcg?uin=a"+id;//故意製造錯誤引發重試
        var url2 = "http://g.qzone.qq.com/fcg-bin/cgi_emotion_list.fcg?uin=b"+id;//故意再次製造錯誤引發重試
        var url3 = "http://g.qzone.qq.com/fcg-bin/cgi_emotion_list.fcg?uin="+id;
        var callback = function(id){ return function(data){
            document.getElementById(id).innerHTML = data.visitcount;
            }
        }(id);
        var errcallback = function(id){ return function(){
            document.getElementById(id).innerHTML = "無法連線到伺服器";
            }
        }(id);
        loadjs(url,callback,errcallback,url2,url3);
    }
}
</SCRIPT>
</HEAD>
<BODY onload="init()">
12345(非法帳號)的訪問量:<span id="12345"></span><BR>
123456 的訪問量:<span id="123456"></span><BR>
20050606 的訪問量:<span id="20050606"></span><BR>
</BODY>
</HTML>


故意在前兩次請求中製造了錯誤,嘗試到第三個url的時候才成功。