指令碼繫結回撥增強版:備用url可以失敗重試
阿新 • • 發佈:2019-01-07
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的時候才成功。