欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

一種模仿線程的Javascript異步模型設計&實現

系統 2762 0

jQuery中所支持的異步模型為:

  • Callbacks,回調函數列隊。
  • Deferred,延遲執行對象。
  • Promise,是Deferred只暴露非狀態改變方法的對象。

這些模型都很漂亮,但我想要一種更帥氣的異步模型。

?

Thread?

我們知道鏈式操作是可以很好的表征運行順序的(可以參考我的文章《 jQuery鏈式操作 》),然而通常基于回調函數或者基于事件監聽的異步模型中,代碼的執行順序不清晰。

Callbacks模型實際上類似一個自定義事件的回調函數隊列,當觸發該事件(調用Callbacks.fire())時,則回調隊列中的所有回調函數。

Deferred是個延遲執行對象,可以注冊Deferred成功、失敗或進行中狀態的回調函數,然后通過觸發相應的事件來回調函數。

這兩種異步模型都類似于事件監聽異步模型,實質上順序依然是分離的。

當然Promise看似能提供我需要的東西,比如Promise.then().then().then()。但是,Promise雖然成功用鏈式操作明確了異步編程的順序執行,但是沒有循環,成功和失敗分支是通過內部代碼確定的。

個人認為,Promise是為了規范化后端nodejs中I/O操作異步模型的,因為I/O狀態只有成功和失敗兩種狀態,所以他是非常成功的。

但在前端,要么只有成功根本沒有失敗,要么不止只有兩種狀態,不應當固定只提供三種狀態的方案,我覺得應該提供可表征多狀態的異步方案。

這個大家可以在something more看到。

我想要一種類似于線程的模型,我們在這里稱為Thread,也就是他能順序執行、也能循環執行、當然還有分支執行。

?

順序執行

線程的順序執行流程,也就是類似于:

      
        do1();
do2();
do3();
      
    

這樣就是依次執行do1,do2,do3。因為這是異步模型,所以我們希望能添加wait方法,即類似于:

      
        do1();
wait(
      
      1000);    
      
        //
      
      
        等待1000ms
      
      
        do2();
wait(
      
      1000);    
      
        //
      
      
        等待1000ms
      
      
        do3();
wait(
      
      1000);    
      
        //
      
      
        等待1000ms
      
    

不使用編譯方法的話,使用鏈式操作來表征順序,則實現后的樣子應當是這樣的:

      Thread().    
      
        //
      
      
        獲取線程
      
      
then(do1).    
      
        //
      
      
        然后執行do1
      
      
wait(1000).    
      
        //
      
      
        等待1000ms
      
      
then(do2).    
      
        //
      
      
        然后執行do2
      
      
wait(1000).    
      
        //
      
      
        等待1000ms
      
      
then(do3).    
      
        //
      
      
        然后執行do3
      
      
wait(1000);    
      
        //
      
      
        等待1000ms
      
    

?

循環執行

循環這很好理解,比如for循環:

      
        for
      
      (; 
      
        true
      
      
        ;){
    
      
      
        dosomething
      
      
        ();
    wait(1000);
}
      
    

進行無限次循環執行do,并且每次都延遲1000ms。則其鏈式表達應當是這樣的:

      Thread().    
      
        //
      
      
        獲取線程
      
      
loop(
      
        -1
      
      ).    
      
        //
      
      
        循環開始,正數則表示循環正數次,負數則表示循環無限次
      
      
    then(
      
        dosomething
      
      ).    
      
        //
      
      
        然后執行do
      
      
    wait(1000).    
      
        //
      
      
        等待1000ms
      
      
loopEnd();    
      
        //
      
      
        循環結束
      
    

這個可以參考后面的例子。?

?

分支執行

分支也就是if...else,比如:

      
        if
      
      (
      
        true
      
      
        ){
    doSccess();
}
      
      
        else
      
      
        {
    doFail();
}
      
    

那么其鏈式實現應當是:

      Thread().    
      
        //
      
      
        獲得線程
      
      
right(
      
        true
      
      ).    
      
        //
      
      
        如果表達式正確
      
      
    then(doSccess).    
      
        //
      
      
        執行doSccess
      
      
left().    
      
        //
      
      
        否則
      
      
    then(doFail).    
      
        //
      
      
        執行doFail
      
      
leftEnd().    
      
        //
      
      
        left分支結束
      
      
rightEnd();    
      
        //
      
      
        right分支結束
      
    

?

聲明變量

聲明變量也就是:

      
        var
      
       a = "hello world!";
    

可被其它函數使用。那么我們的實現是:

      Thread().    
      
        //
      
      
        得到線程
      
      
define("hello world!").    
      
        //
      
      
        將回調函數第一個參數設為hello world!
      
      
then(
      
        function
      
      (a){alert(a);});    
      
        //
      
      
        獲取變量a,alert出來
      
    

?

順序執行實現方案

一種模仿線程的Javascript異步模型設計&實現_第1張圖片 Thread實際上是一個打包函數Fn隊列。

所謂打包函數就是將回調函數打包后產生的新的函數,舉個例子:

      
        function package(callback){
    return function(){
        callback();
        // 干其他事情
    }
}
      
    

這樣我們就將callback函數打包起來了。

Thread提供一個fire方法來觸發線程取出一個打包函數然后執行,打包函數執行以后回調Thread的fire方法。

一種模仿線程的Javascript異步模型設計&實現_第2張圖片

那么我們就可以順序執行函數了。

現在只要打包的時候設置setTimeout執行,則這個線程就能實現wait方法了。

?

循環執行實現方案

循環Loop是一個Thread的變形,只不過在執行里面的打包函數的時候使用另外一種方案,通過添加一個指針取出,執行完后觸發Loop繼續,移動指針取出下一個打包函數。

一種模仿線程的Javascript異步模型設計&實現_第3張圖片

?

分支執行實現方案

分支Right和Left也是Thread的一種變形,開啟分支的時候,主Thread會創建兩個分支Right線程和Left線程,打包一個觸發分支Thread的函數推入隊列,然后當執行到該函數的時候判斷觸發哪個分支執行。

一種模仿線程的Javascript異步模型設計&實現_第4張圖片

其中一個隊列執行結束后回調主Thread,通知進行下一步。?

?

例子

由于該方案和wind-asycn非常相似,所以我們拿wind.js中的clock例子進行改造看看其中的差別吧。

wind.js中的例子:

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <title>Clock - Wind.js Sample</title>
    <meta http-equiv="X-UA-Compatible" content="IE=9" />    
    
    <script src="http://www.cnblogs.com/../src/wind-core.js"></script>
    <script src="http://www.cnblogs.com/../src/wind-compiler.js"></script>
    <script src="http://www.cnblogs.com/../src/wind-builderbase.js"></script>
    <script src="http://www.cnblogs.com/../src/wind-async.js"></script>

    <script>
        var drawHand = function(value, length) {
            ctx.beginPath();
            
            var angle = Math.PI * 2 * value / 60;
            var x = Math.sin(angle) * length;
            var y = Math.cos(angle) * length;
            
            ctx.moveTo(100, 100);
            ctx.lineTo(100 + x, 100 - y);
            ctx.stroke();
        }
    
        var drawClock = function(time) {
            if (!ctx) {
                var h = time.getHours();
                var m = time.getMinutes();
                var s = time.getSeconds();
                
                var text = 
                    ((h >= 10) ? h : "0" + h) + ":" +
                    ((h >= 10) ? m : "0" + m) + ":" +
                    ((h >= 10) ? s : "0" + s);
                
                document.getElementById("clockText").innerHTML = text;
                return;
            }
        
            ctx.clearRect(0, 0, 200, 200);
            
            ctx.beginPath();
            ctx.arc(100, 100, 90, 0, Math.PI * 2, false);
            for (var i = 0; i < 60; i += 5) {
                var angle = Math.PI * 2 * i / 60;
                var x = Math.sin(angle);
                var y = Math.cos(angle);
                ctx.moveTo(100 + x * 85, 100 - y * 85);
                ctx.lineTo(100 + x * 90, 100 - y * 90);
            }
            ctx.stroke();
            
            drawHand(time.getSeconds(), 80);
            drawHand(time.getMinutes() + time.getSeconds() * 1.0 / 60, 60);
            drawHand(time.getHours() % 12 * 5 + time.getMinutes() * 1.0 / 12, 40);
        }
    
        var drawClockAsync = eval(Wind.compile("async", function(interval) {
            while (true) {
                drawClock(new Date());
                $await(Wind.Async.sleep(interval));
            }
        }));
    </script>
</head>
<body>
    <canvas id="clockCanvas" height="200" width="200">
        <div id="clockText" style="font-size:20pt;"></div>
    </canvas>
    <script>
        var canvas = document.getElementById("clockCanvas");
        var ctx = canvas.getContext ? canvas.getContext("2d") : null;
        drawClockAsync(1000).start();
    </script>
</body>
</html>

    

我的例子:

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <title>Clock - asThread.js Sample</title>
    <meta http-equiv="X-UA-Compatible" content="IE=9" />    
    <!-- 例子修改自wind.js -->
    <script src="asThread.js"></script>

    <script>
        var drawHand = function(value, length) {
            ctx.beginPath();
            
            var angle = Math.PI * 2 * value / 60;
            var x = Math.sin(angle) * length;
            var y = Math.cos(angle) * length;
            
            ctx.moveTo(100, 100);
            ctx.lineTo(100 + x, 100 - y);
            ctx.stroke();
        }
    
        var drawClock = function() {
            var time = new Date()
            if (!ctx) {
                var h = time.getHours();
                var m = time.getMinutes();
                var s = time.getSeconds();
                
                var text = 
                    ((h >= 10) ? h : "0" + h) + ":" +
                    ((h >= 10) ? m : "0" + m) + ":" +
                    ((h >= 10) ? s : "0" + s);
                
                document.getElementById("clockText").innerHTML = text;
                return;
            }
        
            ctx.clearRect(0, 0, 200, 200);
            
            ctx.beginPath();
            ctx.arc(100, 100, 90, 0, Math.PI * 2, false);
            for (var i = 0; i < 60; i += 5) {
                var angle = Math.PI * 2 * i / 60;
                var x = Math.sin(angle);
                var y = Math.cos(angle);
                ctx.moveTo(100 + x * 85, 100 - y * 85);
                ctx.lineTo(100 + x * 90, 100 - y * 90);
            }
            ctx.stroke();
            
            drawHand(time.getSeconds(), 80);
            drawHand(time.getMinutes() + time.getSeconds() * 1.0 / 60, 60);
            drawHand(time.getHours() % 12 * 5 + time.getMinutes() * 1.0 / 12, 40);
            
        }
        
        Thread().    // 使用主線程線程
        loop(-1).    // 負數表示循環無限多次,如果是正數n,則表示n次循環
            then(drawClock). // 循環中運行drawClock
            wait(1000).    // 然后等待1000ms
        loopEnd();    // 循環結束
        // 線程定義結束
    </script>
</head>
<body>
    <canvas id="clockCanvas" height="200" width="200">
        <div id="clockText" style="font-size:20pt;"></div>
    </canvas>
    <script>
        var canvas = document.getElementById("clockCanvas");
        var ctx = canvas.getContext ? canvas.getContext("2d") : null;
        Thread().run();    // 運行線程
    </script>
</body>
</html>

    

Something more?

  • 將事件當成分支處理

我們提供了on方法將事件轉成分支來執行。

舉個例子頁面有個按鈕“點我”,但是我們希望打開頁面5秒內單擊沒有效,5秒后顯示“請點擊按鈕”后,單擊才會出現“你成功點擊了”。

使用on分支是這樣的:

        
          <!
        
        
          DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
        
        
          >
        
        
          <
        
        
          html
        
        
          >
        
        
          <
        
        
          head
        
        
          >
        
        
          <
        
        
          title
        
        
          >
        
        on - asThread.js Sample
        
          </
        
        
          title
        
        
          >
        
        
          <
        
        
          meta 
        
        
          http-equiv
        
        
          ="X-UA-Compatible"
        
        
           content
        
        
          ="IE=9"
        
        
          />
        
        
          <
        
        
          script 
        
        
          src
        
        
          ="asThread.js"
        
        
          ></
        
        
          script
        
        
          >
        
        
          </
        
        
          head
        
        
          >
        
        
          <
        
        
          body
        
        
          >
        
        
          <
        
        
          button 
        
        
          id 
        
        
          = "b"
        
        
          >
        
        點我
        
          </
        
        
          button
        
        
          >
        
        
          <
        
        
          script
        
        
          >
        
        
          var
        
        
           ele 
        
        
          =
        
        
           document.getElementById(
        
        
          "
        
        
          b
        
        
          "
        
        
          );
    
        Thread().    
        
        
          //
        
        
           獲得線程
        
        
                  then(
        
        
          function
        
        
          (){alert(
        
        
          "
        
        
          請點擊按鈕
        
        
          "
        
        
          )}, 
        
        
          5000
        
        
          ).    
        
        
          //
        
        
          然后等5秒顯示"請點擊按鈕"
        
        
                  on(ele, 
        
        
          "
        
        
          click
        
        
          "
        
        
          ).    
        
        
          //
        
        
           事件分支On開始,如果ele觸發了click事件
        
        
                      then(
        
        
          function
        
        
          (){alert(
        
        
          "
        
        
          你成功點擊了
        
        
          "
        
        
          )}).    
        
        
          //
        
        
          那么執行你成功點擊了
        
        
                  onEnd().    
        
        
          //
        
        
           事件分支On結束
        
        
                  then(
        
        
          function
        
        
          (){alert(
        
        
          "
        
        
          都說可以的了
        
        
          "
        
        
          )}).    
        
        
          //
        
        
           然后彈出"都說可以的了"
        
        
                  run();    
        
        
          //
        
        
          啟動線程
        
        
          </
        
        
          script
        
        
          >
        
        
          </
        
        
          body
        
        
          >
        
        
          </
        
        
          html
        
        
          >
        
      

自定義事件也可以哦,只要在.on時候傳進去注冊監聽函數,和刪除監聽函數就行了。比如:

        
          function
        
        
           addEvent(__elem, __type, __handler){
    
        
        
          //
        
        
          添加監聽
        
        
          }


        
        
          function
        
        
           removeEvent(__elem, __type, __handler){
    
        
        
          //
        
        
          刪除監聽
        
        
          }

Thread().
on(ele, 
        
        "success"
        
          , addEvent, removeEvent).
    then(
        
        
          function
        
        (){alert("成功!"
        
          )}).
onEnd().
run();
        
      

當然實際上我們還可以注冊多個事件分支。事件分支是并列的,也就是平級的事件分支沒有現有順序,所以我們能這樣:

        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <title>on - asThread.js Sample</title>
    <meta http-equiv="X-UA-Compatible" content="IE=9" />    
    <script src="asThread.js"></script>
</head>
<body>
    <button id = "b">點我</button>
    <button id = "c">點我</button>
    <script>
        
        
          var
        
         ele0 = document.getElementById("b"
        
          ),
              ele1 
        
        = document.getElementById("c"
        
          );
    
        Thread().    
        
        
          //
        
        
           獲得線程
        
        
        then(
        
          function
        
        (){alert("請點擊按鈕")}, 5000).    
        
          //
        
        
          然后等5秒顯示"請點擊按鈕"
        
        
        on(ele0, "click").    
        
          //
        
        
           事件分支On開始,如果ele0觸發了click事件
        
        
            then(
        
          function
        
        (){alert("你成功點擊了")}).    
        
          //
        
        
          那么執行你成功點擊了
        
        
        on(ele1, "click").    
        
          //
        
        
           事件分支On開始,如果ele1觸發了click事件
        
        
            then(
        
          function
        
        (){alert("你成功點擊了")}).    
        
          //
        
        
          那么執行你成功點擊了
        
        
        onEnd().    
        
          //
        
        
           事件分支On結束
        
        
        then(
        
          function
        
        (){alert("都說可以的了")}).    
        
          //
        
        
           然后彈出"都說可以的了"
        
        
        run();    
        
          //
        
        
          啟動線程
        
        
    </script>
</body>
</html>    
      
  • 開辟多個線程

一個線程不夠用?只要輸入名字就能開辟或者得到線程了。

系統會自動初始化一個主線程,當不傳參數時就直接返回主線程:

        Thread() 
        
          //
        
        
          得到主線程
        
      

但如果主線程正在用想開辟一個線程時,只要給個名字就行,比如:

        Thread("hello")    
        
          //
        
        
          得到名字是hello的線程
        
      

那么下次再想用該線程時只要輸入相同的名字就行了:

        Thread("hello")    
        
          //
        
        
          得到hello線程
        
      

默認只最多只提供10個線程,所以用完記得刪掉:

        Thread("hello").del();
      
  • setImmediate

IE10已經提供了setImmediate方法,而其他現代瀏覽器也可以模擬該方法,其原理是推倒線程末端,使得瀏覽器畫面能渲染,得到比setTimeout(0)更快的響應。

我們通過接口.imm來提供這一功能。比如:

        
          Thread().
imm(
        
        
          function
        
        (){alert("hello world"
        
          )}).
run();
        
      

這方法和.then(fn)不太一樣,.then(fn)是可能阻塞當前瀏覽器線程的,但.imm(fn)是將處理推到瀏覽器引擎列隊末端,排到隊了在運行。

所以如果你使用多個Thread(偽多線程),而又希望確保線程是并行運行的,那么請使用.imm來替代.then。

當然對于老版IE,只能用setTimeout(0)替代了。

  • 分支參數可以是函數

分支Right傳的參數如果只是布爾值肯定很不爽,因為這意味著分支是靜態的,在初始化時候就決定了,但我們希望分支能在執行到的時候再判斷是走Right還是Left,所以我們提供了傳參可以是函數(但是函數返回值需要是布爾值,否則……╮(╯▽╰)╭也會轉成布爾值的……哈哈)。比如:

        fucntion foo(
        
          boolean
        
        
          ){
    
        
        
          return
        
         !
        
          boolean
        
        
          ;
}

Thread().
define(
        
        
          true
        
        
          ).
right(foo).
    then(
        
        
          function
        
        (){
        
          /*
        
        
          這里不會運行到*/}).
        
        
          rightEnd().
run();
        
      

Enjoy yourself!!

?

項目地址

https://github.com/miniflycn/asThread

?

一種模仿線程的Javascript異步模型設計&實現


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久精品免费网站 | 97国产精品 | 老头天天吃我奶躁我午夜视频 | 亚洲精品一区二区 | 另类国产ts人妖高潮系列视频 | 欧美日韩在线视频观看 | jyzzjyzzjyzz日本在线观看 | 特黄特色的免费大片看看 | 欧美一级在线播放 | 久久久久久国产视频 | 欧美一级高潮片免费的 | 青青操精品 | 色网站在线免费观看 | 亚洲欧美日韩综合一区久久 | 污视频导航 | 欧美日韩精品一区二区在线播放 | 亚洲国产成人精品女人久久久 | 国产精品日本一区二区不卡视频 | 婷婷久久爱www | 日韩欧美国产偷亚洲清高 | 成人免费毛片aaaaaa片 | 久久综合九色综合欧美狠狠 | 欧美日韩国产欧美 | 一级做a爱过程免费视频麻豆 | 国产一区不卡 | 久久综合婷婷香五月 | 国产精品视频网 | 久久国内精品 | 欧美四虎 | 国产乱在线观看视频 | 天天干国产 | 亚洲国产精品网站 | 91射射射| 欧美成人性生活 | 日韩黄色一级毛片 | 国产婷婷色综合AV蜜臀AV | 精品国产色 | 高清乱码一卡二卡插曲A | 魔法骑士在线观看免费完整版 | 色噜噜狠狠网站 | 黄色网页免费 |