亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

一種模仿線程的Javascript異步模型設(shè)計(jì)&實(shí)現(xiàn)

系統(tǒng) 2669 0

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

  • Callbacks,回調(diào)函數(shù)列隊(duì)。
  • Deferred,延遲執(zhí)行對(duì)象。
  • Promise,是Deferred只暴露非狀態(tài)改變方法的對(duì)象。

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

?

Thread?

我們知道鏈?zhǔn)讲僮魇强梢院芎玫谋碚鬟\(yùn)行順序的(可以參考我的文章《 jQuery鏈?zhǔn)讲僮? 》),然而通常基于回調(diào)函數(shù)或者基于事件監(jiān)聽的異步模型中,代碼的執(zhí)行順序不清晰。

Callbacks模型實(shí)際上類似一個(gè)自定義事件的回調(diào)函數(shù)隊(duì)列,當(dāng)觸發(fā)該事件(調(diào)用Callbacks.fire())時(shí),則回調(diào)隊(duì)列中的所有回調(diào)函數(shù)。

Deferred是個(gè)延遲執(zhí)行對(duì)象,可以注冊(cè)Deferred成功、失敗或進(jìn)行中狀態(tài)的回調(diào)函數(shù),然后通過觸發(fā)相應(yīng)的事件來回調(diào)函數(shù)。

這兩種異步模型都類似于事件監(jiān)聽異步模型,實(shí)質(zhì)上順序依然是分離的。

當(dāng)然Promise看似能提供我需要的東西,比如Promise.then().then().then()。但是,Promise雖然成功用鏈?zhǔn)讲僮髅鞔_了異步編程的順序執(zhí)行,但是沒有循環(huán),成功和失敗分支是通過內(nèi)部代碼確定的。

個(gè)人認(rèn)為,Promise是為了規(guī)范化后端nodejs中I/O操作異步模型的,因?yàn)镮/O狀態(tài)只有成功和失敗兩種狀態(tài),所以他是非常成功的。

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

這個(gè)大家可以在something more看到。

我想要一種類似于線程的模型,我們?cè)谶@里稱為Thread,也就是他能順序執(zhí)行、也能循環(huán)執(zhí)行、當(dāng)然還有分支執(zhí)行。

?

順序執(zhí)行

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

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

這樣就是依次執(zhí)行do1,do2,do3。因?yàn)檫@是異步模型,所以我們希望能添加wait方法,即類似于:

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

不使用編譯方法的話,使用鏈?zhǔn)讲僮鱽肀碚黜樞颍瑒t實(shí)現(xiàn)后的樣子應(yīng)當(dāng)是這樣的:

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

?

循環(huán)執(zhí)行

循環(huán)這很好理解,比如for循環(huán):

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

進(jìn)行無限次循環(huán)執(zhí)行do,并且每次都延遲1000ms。則其鏈?zhǔn)奖磉_(dá)應(yīng)當(dāng)是這樣的:

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

這個(gè)可以參考后面的例子。?

?

分支執(zhí)行

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

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

那么其鏈?zhǔn)綄?shí)現(xiàn)應(yīng)當(dāng)是:

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

?

聲明變量

聲明變量也就是:

      
        var
      
       a = "hello world!";
    

可被其它函數(shù)使用。那么我們的實(shí)現(xiàn)是:

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

?

順序執(zhí)行實(shí)現(xiàn)方案

一種模仿線程的Javascript異步模型設(shè)計(jì)&實(shí)現(xiàn)_第1張圖片 Thread實(shí)際上是一個(gè)打包函數(shù)Fn隊(duì)列。

所謂打包函數(shù)就是將回調(diào)函數(shù)打包后產(chǎn)生的新的函數(shù),舉個(gè)例子:

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

這樣我們就將callback函數(shù)打包起來了。

Thread提供一個(gè)fire方法來觸發(fā)線程取出一個(gè)打包函數(shù)然后執(zhí)行,打包函數(shù)執(zhí)行以后回調(diào)Thread的fire方法。

一種模仿線程的Javascript異步模型設(shè)計(jì)&實(shí)現(xiàn)_第2張圖片

那么我們就可以順序執(zhí)行函數(shù)了。

現(xiàn)在只要打包的時(shí)候設(shè)置setTimeout執(zhí)行,則這個(gè)線程就能實(shí)現(xiàn)wait方法了。

?

循環(huán)執(zhí)行實(shí)現(xiàn)方案

循環(huán)Loop是一個(gè)Thread的變形,只不過在執(zhí)行里面的打包函數(shù)的時(shí)候使用另外一種方案,通過添加一個(gè)指針取出,執(zhí)行完后觸發(fā)Loop繼續(xù),移動(dòng)指針取出下一個(gè)打包函數(shù)。

一種模仿線程的Javascript異步模型設(shè)計(jì)&實(shí)現(xiàn)_第3張圖片

?

分支執(zhí)行實(shí)現(xiàn)方案

分支Right和Left也是Thread的一種變形,開啟分支的時(shí)候,主Thread會(huì)創(chuàng)建兩個(gè)分支Right線程和Left線程,打包一個(gè)觸發(fā)分支Thread的函數(shù)推入隊(duì)列,然后當(dāng)執(zhí)行到該函數(shù)的時(shí)候判斷觸發(fā)哪個(gè)分支執(zhí)行。

一種模仿線程的Javascript異步模型設(shè)計(jì)&實(shí)現(xiàn)_第4張圖片

其中一個(gè)隊(duì)列執(zhí)行結(jié)束后回調(diào)主Thread,通知進(jìn)行下一步。?

?

例子

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

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).    // 負(fù)數(shù)表示循環(huán)無限多次,如果是正數(shù)n,則表示n次循環(huán)
            then(drawClock). // 循環(huán)中運(yùn)行drawClock
            wait(1000).    // 然后等待1000ms
        loopEnd();    // 循環(huán)結(jié)束
        // 線程定義結(jié)束
    </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();    // 運(yùn)行線程
    </script>
</body>
</html>

    

Something more?

  • 將事件當(dāng)成分支處理

我們提供了on方法將事件轉(zhuǎn)成分支來執(zhí)行。

舉個(gè)例子頁(yè)面有個(gè)按鈕“點(diǎn)我”,但是我們希望打開頁(yè)面5秒內(nèi)單擊沒有效,5秒后顯示“請(qǐng)點(diǎn)擊按鈕”后,單擊才會(huì)出現(xiàn)“你成功點(diǎn)擊了”。

使用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"
        
        
          >
        
        點(diǎn)我
        
          </
        
        
          button
        
        
          >
        
        
          <
        
        
          script
        
        
          >
        
        
          var
        
        
           ele 
        
        
          =
        
        
           document.getElementById(
        
        
          "
        
        
          b
        
        
          "
        
        
          );
    
        Thread().    
        
        
          //
        
        
           獲得線程
        
        
                  then(
        
        
          function
        
        
          (){alert(
        
        
          "
        
        
          請(qǐng)點(diǎn)擊按鈕
        
        
          "
        
        
          )}, 
        
        
          5000
        
        
          ).    
        
        
          //
        
        
          然后等5秒顯示"請(qǐng)點(diǎn)擊按鈕"
        
        
                  on(ele, 
        
        
          "
        
        
          click
        
        
          "
        
        
          ).    
        
        
          //
        
        
           事件分支On開始,如果ele觸發(fā)了click事件
        
        
                      then(
        
        
          function
        
        
          (){alert(
        
        
          "
        
        
          你成功點(diǎn)擊了
        
        
          "
        
        
          )}).    
        
        
          //
        
        
          那么執(zhí)行你成功點(diǎn)擊了
        
        
                  onEnd().    
        
        
          //
        
        
           事件分支On結(jié)束
        
        
                  then(
        
        
          function
        
        
          (){alert(
        
        
          "
        
        
          都說可以的了
        
        
          "
        
        
          )}).    
        
        
          //
        
        
           然后彈出"都說可以的了"
        
        
                  run();    
        
        
          //
        
        
          啟動(dòng)線程
        
        
          </
        
        
          script
        
        
          >
        
        
          </
        
        
          body
        
        
          >
        
        
          </
        
        
          html
        
        
          >
        
      

自定義事件也可以哦,只要在.on時(shí)候傳進(jìn)去注冊(cè)監(jiān)聽函數(shù),和刪除監(jiān)聽函數(shù)就行了。比如:

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


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

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

當(dāng)然實(shí)際上我們還可以注冊(cè)多個(gè)事件分支。事件分支是并列的,也就是平級(jí)的事件分支沒有現(xiàn)有順序,所以我們能這樣:

        <!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">點(diǎn)我</button>
    <button id = "c">點(diǎn)我</button>
    <script>
        
        
          var
        
         ele0 = document.getElementById("b"
        
          ),
              ele1 
        
        = document.getElementById("c"
        
          );
    
        Thread().    
        
        
          //
        
        
           獲得線程
        
        
        then(
        
          function
        
        (){alert("請(qǐng)點(diǎn)擊按鈕")}, 5000).    
        
          //
        
        
          然后等5秒顯示"請(qǐng)點(diǎn)擊按鈕"
        
        
        on(ele0, "click").    
        
          //
        
        
           事件分支On開始,如果ele0觸發(fā)了click事件
        
        
            then(
        
          function
        
        (){alert("你成功點(diǎn)擊了")}).    
        
          //
        
        
          那么執(zhí)行你成功點(diǎn)擊了
        
        
        on(ele1, "click").    
        
          //
        
        
           事件分支On開始,如果ele1觸發(fā)了click事件
        
        
            then(
        
          function
        
        (){alert("你成功點(diǎn)擊了")}).    
        
          //
        
        
          那么執(zhí)行你成功點(diǎn)擊了
        
        
        onEnd().    
        
          //
        
        
           事件分支On結(jié)束
        
        
        then(
        
          function
        
        (){alert("都說可以的了")}).    
        
          //
        
        
           然后彈出"都說可以的了"
        
        
        run();    
        
          //
        
        
          啟動(dòng)線程
        
        
    </script>
</body>
</html>    
      
  • 開辟多個(gè)線程

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

系統(tǒng)會(huì)自動(dòng)初始化一個(gè)主線程,當(dāng)不傳參數(shù)時(shí)就直接返回主線程:

        Thread() 
        
          //
        
        
          得到主線程
        
      

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

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

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

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

默認(rèn)只最多只提供10個(gè)線程,所以用完記得刪掉:

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

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

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

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

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

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

當(dāng)然對(duì)于老版IE,只能用setTimeout(0)替代了。

  • 分支參數(shù)可以是函數(shù)

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

        fucntion foo(
        
          boolean
        
        
          ){
    
        
        
          return
        
         !
        
          boolean
        
        
          ;
}

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

Enjoy yourself!!

?

項(xiàng)目地址

https://github.com/miniflycn/asThread

?

一種模仿線程的Javascript異步模型設(shè)計(jì)&實(shí)現(xiàn)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

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

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 日韩免费精品一级毛片 | 久久精品国产精品亚洲婷婷 | 国产91在线 | 日韩 | 在线资源站| 国内成人免费视频 | 午夜视频免费国产在线 | 久久精品vr中文字幕 | 在线成人免费观看国产精品 | 国产精品亚欧美一区二区三区 | 国产视频自拍一区 | 亚洲图片欧美视频 | 一级激情视频 | 全黄h全肉边做边吃奶在线观看 | 久久精品国产一区二区三区日韩 | 国产综合精品 | 中文字幕在线视频免费观看 | 国产真实偷乱视频在线观看 | 国内精品视频一区二区三区八戒 | 99re8免费视频精品全部 | 亚洲在线观看 | 亚洲男人的天堂久久香蕉网 | 99久久精品免费观看国产 | 久久精品国产精品国产精品污 | 亚洲一区二区三区视频 | 国产在线拍国产拍拍偷 | 亚洲视频www | 亚洲欧美一区二区三区国产精品 | 亚洲+自拍+色综合图区一 | 另类色综合 | 在线播放69热精品视频 | 自拍亚洲国产 | 波多野结衣一区二区三区 | 亚洲视频毛片 | 在线亚洲精品国产波多野结衣 | 亚洲国产男人本色在线观看的a站 | 日日射日日干 | 亚洲最黄视频 | 九九热视频精品 | 久久久久欧美精品网站 | 久久无码精品一区二区三区 | 欧美日韩国产最新一区二区 |