<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      異步javascript的原理和實現

      因為工作的需要,我要在網頁端編寫一段腳本,把數據通過網頁批量提交到系統中去。所以我就想到了Greasemonkey插件,于是就開始動手寫,發現問題解決得很順利。但是在對腳本進行總結和整理的時候,我習慣性地問了自己一個問題:能不能再簡單點?

      我的答案當然是“能”。

      首先回顧我的數據批量提交的需求:我有一批用戶數據要插入到系統中,但是因為系統庫表結構不是行列式的,所以無法轉化為sql語句插入。要插入的數據有接近200條,就是傻呵呵地手工錄入到系統,估計也要1天的時間。作為程序員,當然不會干這么傻的事情,我一定要用程序來解決。這個編程的過程耗費了我1天的時間。相比手工錄入,我額外收入是這篇博文,絕對的合算!

      編程平臺選擇沒花費時間,直接選定基于Greasemonkey寫自己的腳本,瀏覽器當然是firefox了。腳本的工作過程:

      1. 在腳本中預先存放要插入的數據
      2. 模擬鼠標點擊,打開頁面中的輸入窗口
      3. 將數據錄入到輸入窗口,并模擬點擊“提交”按鈕,將數據提交到系統中。
      4. 依次循環,直到所有數據都處理完畢。

      這里的技術難點在于:

      1. 打開輸入窗口,需要等待不定期的時間,視網絡情況而定。
      2. 提交數據到后臺,需要等待處理完畢之后才可以循環下一個數據。

      如果我是菜鳥的話,我當然直接寫一個類似這樣的應用邏輯:

         1:  for(var i = 0; i < dataArray.length; ++i)
         2:  {
         3:      clickButtonForInputWindow();
         4:      waitInputWindow();
         5:      enterInputData(dataArray[i]);
         6:      clickSubmitButton();
         7:      waitInputWindowClose();
         8:  }

      實際上這樣寫所有瀏覽器都會陷入一片白屏,并在若干分鐘之后提示“沒有響應”而被強行終止掉。原因就是瀏覽器在調用javascript的時候,主界面是停止響應的,因為cpu交給js執行了,沒有時間去處理界面消息。

      為了滿足“不鎖死”的要求,我們可以把腳本修改成這樣:

         1:  for(var i = 0; i < dataArray.length; ++i)
         2:  {
         3:      setTimeout(clickButtonForInputWindow);
         4:  
         5:      setTimeout(waitInputWindowClose);
         6:  }

      實際上setTimeout和setInterval是瀏覽器唯一可以支持異步的操作。如何更優雅地使用這兩個函數來實現異步操作呢?目前簡單的答案是老趙Wind.js。雖然我沒有用過這個函數庫,但是光是$await調用,就是符合我一貫對簡潔的要求的。但是對于我這樣的單個文件的腳本來說,去網上下載一個外部js庫,明顯不如有一段支持異步操作的代碼拷貝過來的快和爽。

      所以我決定另辟蹊徑,做一個不要編譯而且易用性還可以更能夠Copy&Paste的異步函數庫。

      說異步之前,我們一起回憶一下同步操作的幾種結構類型:

      1. 順序:就是語句的先后順序執行
      2. 判斷:就是判斷語句
      3. 循環:嚴格來說應該是跳轉(goto),但大多數現代語言都取消了goto。循環其實應該是復合結構,是if和goto的組合體。

      異步操作的難點在兩個地方:

      1. 異步的判斷:異步情況下的判斷基本都是檢測條件十分滿足,然后執行某些動作。
      2. 異步的順序:順序中的每一步操作之后都要交回控制權,等待在下一個時間片中繼續執行下一步。難點是如何保持順序性。尤其在兩個順序動作中間夾雜一個異步的循環的時候。
      3. 異步的循環:每次循環之后都交回控制權到瀏覽器,如此循環,直到運行結束。

      最簡單的實現當然就是異步循環了,我的實現代碼如下:

         1:  function asyncWhile(fn, interval) 
         2:  { 
         3:      if( fn == null || (typeof(fn) != "string" && typeof(fn) != "function") ) 
         4:          return; 
         5:      var wrapper = function() 
         6:      { 
         7:          if( (typeof(fn) == "function" ? fn() : eval(fn) ) !== false ) 
         8:              setTimeout(wrapper, interval == null? 1: interval); 
         9:      } 
        10:      wrapper(); 
        11:  }
      核心內容就是:如果fn函數返回值不是false,就繼續下一個setTimeout的登記調用。

      實際上,“等待并執行”邏輯,根本上就是一個異步循環問題。這種情況的實現方法示例如下:

         1:  asyncWhile(function(){
         2:      if( xxxCondition == false )
         3:          return true; // 表示繼續循環
         4:      else
         5:          doSomeThing();
         6:      return false; // 表示不需要繼續循環了
         7:  });

      對于非等待并執行的邏輯,簡單一個 setTimeout 就可以了。

      異步容易,實現異步中的順序才叫難度呢。最早的起因是我要實現3步,但是第二部是一個異步的100多次的循環。也就是說,我要實現的3步操作,其實是103次的順序異步操作。為了一個如何在瀏覽器中實現可響應的等待,找破了腦袋,只找到一個firefox中的實現,還要申請特權調用。

      最后想出了一個簡單的方法,就是引入了“執行鏈(Execution Chain)”的概念,同一個執行鏈的所有登記函數是順序的,不同執行鏈之間沒有任何關系。另外,不提供互斥(mutex)等概念,如果要同步,自行在代碼中檢查。

      在同一個執行鏈中,保存一個執行令牌,只有令牌和函數序號匹配,才允許執行,這樣就保證了異步執行的順序性。

         1:      function asyncSeq(funcArray, chainName, abortWhenError)
         2:      {
         3:          if( typeof(funcArray) == "function" )
         4:              return asyncSeq([funcArray], chainName, abortWhenError);
         5:              
         6:          if( funcArray == null || funcArray.length == 0 ) 
         7:              return;
         8:              
         9:          if( chainName == null ) chainName = "__default_seq_chain__";
        10:          var tInfos = asyncSeq.chainInfos = asyncSeq.chainInfos || {};
        11:          var tInfo = tInfos[chainName] = tInfos[chainName] || {count : 0, currentIndex : -1, abort : false};
        12:          
        13:          for(var i = 0; i < funcArray.length; ++i)
        14:          {
        15:              asyncWhile(function(item, tIndex){
        16:                  return function(){
        17:                      if( tInfo.abort )
        18:                          return false;
        19:                      if( tInfo.currentIndex < tIndex )
        20:                          return true;
        21:                      else if( tInfo.currentIndex == tIndex )
        22:                      {
        23:                          try{
        24:                              item();
        25:                          }
        26:                          catch(e){
        27:                              if( abortWhenError ) tInfo.abort = true;
        28:                          }
        29:                          finally{
        30:                              tInfo.currentIndex ++;
        31:                          }
        32:                      }
        33:                      else
        34:                      {
        35:                          if( abortWhenError ) tInfo.abort = true;
        36:                      }
        37:                      return false;
        38:                  };
        39:              }(funcArray[i], tInfo.count ++));
        40:          }
        41:          
        42:          setTimeout(function(){
        43:        if( tInfo.count > 0 && tInfo.currentIndex == -1 )
        44:                  tInfo.currentIndex = 0;
        45:          },20); // 為了調試的原因,加了延遲啟動
        46:      }

      由此,一個支持Copy&Paste的異步js函數庫就完成了。具體的使用例子如下:

         1:      function testAsync()
         2:      {        
         3:          asyncSeq([function(){println("aSyncSeq -0 ");}
         4:              , function(){println("aSyncSeq -1 ");}
         5:              , function(){println("aSyncSeq -2 ");}
         6:              , function(){println("aSyncSeq -3 ");}
         7:              , function(){println("aSyncSeq -4 ");}
         8:              , function(){println("aSyncSeq -5 ");}
         9:              , function(){println("aSyncSeq -6 ");}
        10:              , function(){println("aSyncSeq -7 ");}
        11:              , function(){println("aSyncSeq -8 ");}
        12:              , function(){println("aSyncSeq -9 ");}
        13:              , function(){println("aSyncSeq -10 ");}
        14:              , function(){println("aSyncSeq -11 ");}
        15:              , function(){println("aSyncSeq -12 ");}
        16:              , function(){println("aSyncSeq -13 ");}
        17:              , function(){println("aSyncSeq -14 ");}
        18:              , function(){println("aSyncSeq -15 ");}
        19:              , function(){println("aSyncSeq -16 ");}
        20:              , function(){println("aSyncSeq -17 ");}
        21:              , function(){println("aSyncSeq -18 ");}
        22:              , function(){println("aSyncSeq -19 ");}
        23:              , function(){println("aSyncSeq -20 ");}
        24:              , function(){println("aSyncSeq -21 ");}
        25:              , function(){println("aSyncSeq -22 ");}
        26:              , function(){println("aSyncSeq -23 ");}
        27:              , function(){println("aSyncSeq -24 ");}
        28:              , function(){println("aSyncSeq -25 ");}
        29:              , function(){println("aSyncSeq -26 ");}
        30:              , function(){println("aSyncSeq -27 ");}
        31:              , function(){println("aSyncSeq -28 ");}
        32:              , function(){println("aSyncSeq -29 ");}
        33:          ]);
        34:   
        35:          asyncSeq([function(){println("aSyncSeq test-chain -a0 ");}
        36:              , function(){println("aSyncSeq test-chain -a1 ");}
        37:              , function(){println("aSyncSeq test-chain -a2 ");}
        38:              , function(){println("aSyncSeq test-chain -a3 ");}
        39:              , function(){println("aSyncSeq test-chain -a4 ");}
        40:              , function(){println("aSyncSeq test-chain -a5 ");}
        41:              , function(){println("aSyncSeq test-chain -a6 ");}
        42:              , function(){println("aSyncSeq test-chain -a7 ");}
        43:              , function(){println("aSyncSeq test-chain -a8 ");}
        44:          ], "test-chain");
        45:   
        46:          asyncSeq([function(){println("aSyncSeq -a0 ");}
        47:              , function(){println("aSyncSeq -a1 ");}
        48:              , function(){println("aSyncSeq -a2 ");}
        49:              , function(){println("aSyncSeq -a3 ");}
        50:              , function(){println("aSyncSeq -a4 ");}
        51:              , function(){println("aSyncSeq -a5 ");}
        52:              , function(){println("aSyncSeq -a6 ");}
        53:              , function(){println("aSyncSeq -a7 ");}
        54:              , function(){println("aSyncSeq -a8 ");}
        55:          ]);
        56:      }
        57:   
        58:      var textArea = null;
        59:      
        60:      function println(text)
        61:      {
        62:          if( textArea == null )
        63:          {
        64:              textArea = document.getElementById("text");
        65:              textArea.value = "";
        66:          }
        67:          
        68:          textArea.value = textArea.value + text + "\r\n";
        69:      }

      最后,要向大家說一聲抱歉,很多只想拿代碼的朋友恐怕要失望了,如果你真的不知道怎么處理這些多余的行號,你可以學習一下正則表達式的替換,推薦用UltraEdit。

      posted on 2012-11-08 02:13  老翅寒暑  閱讀(8819)  評論(7)    收藏  舉報

      導航

      主站蜘蛛池模板: 噜噜噜噜私人影院| 欧洲中文字幕国产精品| 成人午夜在线观看刺激| 亚洲av无码成人精品区一区| 亚洲国产中文字幕精品| 国产不卡精品视频男人的天堂| 国产一区二区三区韩国| 青青草国产精品一区二区| 精品黄色av一区二区三区| 在线a人片免费观看| 国产精品永久在线观看| 午夜精品一区二区三区成人| gogo无码大胆啪啪艺术| 亚洲人成电影网站 久久影视| 激情综合网激情国产av| 妺妺窝人体色WWW看人体| 国产精品视频全国免费观看| 国产成人无码精品亚洲| 九九久久人妻一区精品色| 影音先锋啪啪av资源网站| 国产av无码专区亚洲av软件| 国产熟妇另类久久久久久| 亚洲久悠悠色悠在线播放| 亚洲综合色婷婷中文字幕| 久久国产精品成人免费| 国产99精品成人午夜在线| 国产片AV国语在线观看手机版| 无码毛片一区二区本码视频| 人妻少妇偷人精品视频| 日本边添边摸边做边爱| 日韩中文字幕亚洲精品一| 国产成人高清亚洲综合| 制服丝袜美腿一区二区| 亚洲av无码牛牛影视在线二区| 亚洲av永久无码精品成人| 玩弄放荡人妻少妇系列| 久久中文字幕无码专区| 日韩av天堂综合网久久| 亚洲高清WWW色好看美女| 亚洲影院丰满少妇中文字幕无码| av无码精品一区二区三区|