精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

JavaScript Event Loop機制詳解與Vue.js中nextTick的實踐應用

開發 前端
本文依次介紹了函數調用棧、MacroTask 與 MicroTask 執行順序、淺析 Vue.js 中 nextTick 實現等內容;本文中引用的參考資料統一聲明在 JavaScript 學習與實踐資料索引。

本文依次介紹了函數調用棧、MacroTask 與 MicroTask 執行順序、淺析 Vue.js 中 nextTick 實現等內容;本文中引用的參考資料統一聲明在 JavaScript 學習與實踐資料索引。

1. 事件循環機制詳解與實踐應用

JavaScript 是典型的單線程單并發語言,即表示在同一時間片內其只能執行單個任務或者部分代碼片。換言之,我們可以認為某個同域瀏覽器上下中 JavaScript 主線程擁有一個函數調用棧以及一個任務隊列(參考 whatwg 規范);主線程會依次執行代碼,當遇到函數時,會先將函數入棧,函數運行完畢后再將該函數出棧,直到所有代碼執行完畢。當函數調用棧為空時,運行時即會根據事件循環(Event Loop)機制來從任務隊列中提取出待執行的回調并執行,執行的過程同樣會進行函數幀的入棧出棧操作。每個線程有自己的事件循環,所以每個 Web Worker有自己的,所以它才可以獨立執行。然而,所有同屬一個 origin 的窗體都共享一個事件循環,所以它們可以同步交流。

Event Loop(事件循環)并不是 JavaScript 中獨有的,其廣泛應用于各個領域的異步編程實現中;所謂的 Event Loop 即是一系列回調函數的集合,在執行某個異步函數時,會將其回調壓入隊列中,JavaScript 引擎會在異步代碼執行完畢后開始處理其關聯的回調。

 

在 Web 開發中,我們常常會需要處理網絡請求等相對較慢的操作,如果將這些操作全部以同步阻塞方式運行無疑會大大降低用戶界面的體驗。另一方面,我們點擊某些按鈕之后的響應事件可能會導致界面重渲染,如果因為響應事件的執行而阻塞了界面的渲染,同樣會影響整體性能。實際開發中我們會采用異步回調來處理這些操作,這種調用者與響應之間的解耦保證了 JavaScript 能夠在等待異步操作完成之前仍然能夠執行其他的代碼。Event Loop 正是負責執行隊列中的回調并且將其壓入到函數調用棧中,其基本的代碼邏輯如下所示:

  1. while (queue.waitForMessage()) { 
  2.  
  3.   queue.processNextMessage(); 
  4.  
  5.  

完整的瀏覽器中 JavaScript 事件循環機制圖解如下:

 

在 Web 瀏覽器中,任何時刻都有可能會有事件被觸發,而僅有那些設置了回調的事件會將其相關的任務壓入到任務隊列中。回調函數被調用時即會在函數調用棧中創建初始幀,而直到整個函數調用棧清空之前任何產生的任務都會被壓入到任務隊列中延后執行;順序的同步函數調用則會創建新的棧幀。總結而言,瀏覽器中的事件循環機制闡述如下:

  • 瀏覽器內核會在其它線程中執行異步操作,當操作完成后,將操作結果以及事先定義的回調函數放入 JavaScript 主線程的任務隊列中。
  • JavaScript 主線程會在執行棧清空后,讀取任務隊列,讀取到任務隊列中的函數后,將該函數入棧,一直運行直到執行棧清空,再次去讀取任務隊列,不斷循環。
  • 當主線程阻塞時,任務隊列仍然是能夠被推入任務的。這也就是為什么當頁面的 JavaScript 進程阻塞時,我們觸發的點擊等事件,會在進程恢復后依次執行。

2. 函數調用棧與任務隊列

在變量作用域與提升一節中我們介紹過所謂執行上下文(Execution Context)的概念,在 JavaScript 代碼執行過程中,我們可能會擁有一個全局上下文,多個函數上下文或者塊上下文;每個函數調用都會創造新的上下文與局部作用域。而這些執行上下文堆疊就形成了所謂的執行上下文棧(Execution Context Stack),便如上文介紹的 JavaScript 是單線程事件循環機制,同時刻僅會執行單個事件,而其他事件都在所謂的執行棧中排隊等待:

 

而從 JavaScript 內存模型的角度,我們可以將內存劃分為調用棧(Call Stack)、堆(Heap)以及隊列(Queue)等幾個部分:

 

其中的調用棧會記錄所有的函數調用信息,當我們調用某個函數時,會將其參數與局部變量等壓入棧中;在執行完畢后,會彈出棧首的元素。而堆則存放了大量的非結構化數據,譬如程序分配的變量與對象。隊列則包含了一系列待處理的信息與相關聯的回調函數,每個 JavaScript 運行時都必須包含一個任務隊列。當調用棧為空時,運行時會從隊列中取出某個消息并且執行其關聯的函數(也就是創建棧幀的過程);運行時會遞歸調用函數并創建調用棧,直到函數調用棧全部清空再從任務隊列中取出消息。換言之,譬如按鈕點擊或者 HTTP 請求響應都會作為消息存放在任務隊列中;需要注意的是,僅當這些事件的回調函數存在時才會被放入任務隊列,否則會被直接忽略。

譬如對于如下的代碼塊:

  1. function fire() { 
  2.  
  3.     const result = sumSqrt(3, 4) 
  4.  
  5.     console.log(result); 
  6.  
  7.  
  8. function sumSqrt(x, y) { 
  9.  
  10.     const s1 = square(x) 
  11.  
  12.     const s2 = square(y) 
  13.  
  14.     const sum = s1 + s2; 
  15.  
  16.     return Math.sqrt(sum
  17.  
  18.  
  19. function square(x) { 
  20.  
  21.     return x * x; 
  22.  
  23.   
  24.  
  25. fire()  

其對應的函數調用圖(整理自這里)為:

 

這里還值得一提的是,Promise.then 是異步執行的,而創建 Promise 實例 (executor) 是同步執行的,譬如下述代碼:

  1. (function test() { 
  2.  
  3.     setTimeout(function() {console.log(4)}, 0); 
  4.  
  5.     new Promise(function executor(resolve) { 
  6.  
  7.         console.log(1); 
  8.  
  9.         for( var i=0 ; i<10000 ; i++ ) { 
  10.  
  11.             i == 9999 && resolve(); 
  12.  
  13.         } 
  14.  
  15.         console.log(2); 
  16.  
  17.     }).then(function() { 
  18.  
  19.         console.log(5); 
  20.  
  21.     }); 
  22.  
  23.     console.log(3); 
  24.  
  25. })() 
  26.  
  27. // 輸出結果為: 
  28.  
  29. // 1 
  30.  
  31. // 2 
  32.  
  33. // 3 
  34.  
  35. // 5 
  36.  
  37. // 4  

我們可以參考 Promise 規范中有關于 promise.then 的部分: 

  1. promise.then(onFulfilled, onRejected)      
  2.  
  3. 2.2.4 onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].     
  4.  
  5. Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called. 

規范要求,onFulfilled 必須在執行上下文棧(Execution Context Stack) 只包含 平臺代碼(platform code) 后才能執行。平臺代碼指引擎,環境,Promise 實現代碼等。實踐上來說,這個要求保證了 onFulfilled 的異步執行(以全新的棧),在 then 被調用的這個事件循環之后。

3. MacroTask(Task) 與 MicroTask(Job)

在面試中我們常常會碰到如下的代碼題,其主要就是考校 JavaScript 不同任務的執行先后順序:

  1. // 測試代碼 
  2.  
  3. console.log('main1'); 
  4.  
  5.   
  6.  
  7. // 該函數僅在 Node.js 環境下可以使用 
  8.  
  9. process.nextTick(function() { 
  10.  
  11.     console.log('process.nextTick1'); 
  12.  
  13. }); 
  14.  
  15.   
  16.  
  17. setTimeout(function() { 
  18.  
  19.     console.log('setTimeout'); 
  20.  
  21.     process.nextTick(function() { 
  22.  
  23.         console.log('process.nextTick2'); 
  24.  
  25.     }); 
  26.  
  27. }, 0); 
  28.  
  29.   
  30.  
  31. new Promise(function(resolve, reject) { 
  32.  
  33.     console.log('promise'); 
  34.  
  35.     resolve(); 
  36.  
  37. }).then(function() { 
  38.  
  39.     console.log('promise then'); 
  40.  
  41. }); 
  42.  
  43.   
  44.  
  45. console.log('main2'); 
  46.  
  47.   
  48.  
  49. // 執行結果 
  50.  
  51. main1 
  52.  
  53. promise 
  54.  
  55. main2 
  56.  
  57. process.nextTick1 
  58.  
  59. promise then 
  60.  
  61. setTimeout 
  62.  
  63. process.nextTick2  

我們在前文中已經介紹過 JavaScript 的主線程在遇到異步調用時,這些異步調用會立刻返回某個值,從而讓主線程不會在此處阻塞。而真正的異步操作會由瀏覽器執行,主線程則會在清空當前調用棧后,按照先入先出的順序讀取任務隊列里面的任務。而 JavaScript 中的任務又分為 MacroTask 與 MicroTask 兩種,在 ES2015 中 MacroTask 即指 Task,而 MicroTask 則是指代 Job。典型的 MacroTask 包含了 setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering 等,MicroTask 包含了 process.nextTick, Promises, Object.observe, MutationObserver 等。 二者的關系可以圖示如下:

 

參考 whatwg 規范 中的描述:一個事件循環(Event Loop)會有一個或多個任務隊列(Task Queue,又稱 Task Source),這里的 Task Queue 就是 MacroTask Queue,而 Event Loop 僅有一個 MicroTask Queue。每個 Task Queue 都保證自己按照回調入隊的順序依次執行,所以瀏覽器可以從內部到JS/DOM,保證動作按序發生。而在 Task 的執行之間則會清空已有的 MicroTask 隊列,在 MacroTask 或者 MicroTask 中產生的 MicroTask 同樣會被壓入到 MicroTask 隊列中并執行。參考如下代碼:

  1. function foo() { 
  2.  
  3.   console.log("Start of queue"); 
  4.  
  5.   bar(); 
  6.  
  7.   setTimeout(function() { 
  8.  
  9.     console.log("Middle of queue"); 
  10.  
  11.   }, 0); 
  12.  
  13.   Promise.resolve().then(function() { 
  14.  
  15.     console.log("Promise resolved"); 
  16.  
  17.     Promise.resolve().then(function() { 
  18.  
  19.       console.log("Promise resolved again"); 
  20.  
  21.     }); 
  22.  
  23.   }); 
  24.  
  25.   console.log("End of queue"); 
  26.  
  27.  
  28.   
  29.  
  30. function bar() { 
  31.  
  32.   setTimeout(function() { 
  33.  
  34.     console.log("Start of next queue"); 
  35.  
  36.   }, 0); 
  37.  
  38.   setTimeout(function() { 
  39.  
  40.     console.log("End of next queue"); 
  41.  
  42.   }, 0); 
  43.  
  44.  
  45.   
  46.  
  47. foo();  
  48.   
  49.  
  50. // 輸出 
  51.  
  52. Start of queue 
  53.  
  54. End of queue 
  55.  
  56. Promise resolved 
  57.  
  58. Promise resolved again 
  59.  
  60. Start of next queue 
  61.  
  62. End of next queue 
  63.  
  64. Middle of queue  

上述代碼中*** TaskQueue 即為 foo(),foo() 又調用了 bar() 構建了新的 TaskQueue,bar() 調用之后 foo() 又產生了 MicroTask 并被壓入了唯一的 MicroTask 隊列。我們***再總計下 JavaScript MacroTask 與 MicroTask 的執行順序,當執行棧(call stack)為空的時候,開始依次執行:

《這一段在我筆記里也放了好久,無法確定是否拷貝的。。。如果有哪位發現請及時告知。。。(*ฅ́˘ฅ̀*)♡》

1)把最早的任務(task A)放入任務隊列

2)如果 task A 為null (那任務隊列就是空),直接跳到第6步

3)將 currently running task 設置為 task A

4)執行 task A (也就是執行回調函數)

5)將 currently running task 設置為 null 并移出 task A

6)執行 microtask 隊列a: 在 microtask 中選出最早的任務 task X

b: 如果 task X 為null (那 microtask 隊列就是空),直接跳到 g

c: 將 currently running task 設置為 task X

d: 執行 task X

e: 將 currently running task 設置為 null 并移出 task X

f: 在 microtask 中選出最早的任務 , 跳到 b

g: 結束 microtask 隊列

1)跳到***步

4. 淺析 Vue.js 中 nextTick 的實現

在 Vue.js 中,其會異步執行 DOM 更新;當觀察到數據變化時,Vue 將開啟一個隊列,并緩沖在同一事件循環中發生的所有數據改變。如果同一個 watcher 被多次觸發,只會一次推入到隊列中。這種在緩沖時去除重復數據對于避免不必要的計算和 DOM 操作上非常重要。然后,在下一個的事件循環“tick”中,Vue 刷新隊列并執行實際(已去重的)工作。Vue 在內部嘗試對異步隊列使用原生的 Promise.then 和 MutationObserver,如果執行環境不支持,會采用 setTimeout(fn, 0) 代替。

《因為本人失誤,原來此處內容拷貝了 https://www.zhihu.com/question/55364497 這個回答,造成了侵權,深表歉意,已經刪除,后續我會在 github 鏈接上重寫本段》

而當我們希望在數據更新之后執行某些 DOM 操作,就需要使用 nextTick 函數來添加回調:

  1. // HTML 
  2.  
  3. <div id="example">{{message}}</div> 
  4.  
  5.   
  6.  
  7. // JS 
  8.  
  9. var vm = new Vue({ 
  10.  
  11.   el: '#example'
  12.  
  13.   data: { 
  14.  
  15.     message: '123' 
  16.  
  17.   } 
  18.  
  19. }) 
  20.  
  21. vm.message = 'new message' // 更改數據 
  22.  
  23. vm.$el.textContent === 'new message' // false 
  24.  
  25. Vue.nextTick(function () { 
  26.  
  27.   vm.$el.textContent === 'new message' // true 
  28.  
  29. })  

在組件內使用 vm.$nextTick() 實例方法特別方便,因為它不需要全局 Vue ,并且回調函數中的 this 將自動綁定到當前的 Vue 實例上:

  1. Vue.component('example', { 
  2.  
  3.   template: '<span>{{ message }}</span>'
  4.  
  5.   data: function () { 
  6.  
  7.     return { 
  8.  
  9.       message: '沒有更新' 
  10.  
  11.     } 
  12.  
  13.   }, 
  14.  
  15.   methods: { 
  16.  
  17.     updateMessage: function () { 
  18.  
  19.       this.message = '更新完成' 
  20.  
  21.       console.log(this.$el.textContent) // => '沒有更新' 
  22.  
  23.       this.$nextTick(function () { 
  24.  
  25.         console.log(this.$el.textContent) // => '更新完成' 
  26.  
  27.       }) 
  28.  
  29.     } 
  30.  
  31.   } 
  32.  
  33. })  

src/core/util/env

  1. /** 
  2.  
  3. * 使用 MicroTask 來異步執行批次任務 
  4.  
  5. */ 
  6.  
  7. export const nextTick = (function() { 
  8.  
  9.   // 需要執行的回調列表 
  10.  
  11.   const callbacks = []; 
  12.  
  13.   
  14.  
  15.   // 是否處于掛起狀態 
  16.  
  17.   let pending = false
  18.  
  19.   
  20.  
  21.   // 時間函數句柄 
  22.  
  23.   let timerFunc; 
  24.  
  25.   
  26.  
  27.   // 執行并且清空所有的回調列表 
  28.  
  29.   function nextTickHandler() { 
  30.  
  31.     pending = false
  32.  
  33.     const copies = callbacks.slice(0); 
  34.  
  35.     callbacks.length = 0; 
  36.  
  37.     for (let i = 0; i < copies.length; i++) { 
  38.  
  39.       copies[i](); 
  40.  
  41.     } 
  42.  
  43.   } 
  44.  
  45.   
  46.  
  47.   // nextTick 的回調會被加入到 MicroTask 隊列中,這里我們主要通過原生的 Promise 與 MutationObserver 實現 
  48.  
  49.   /* istanbul ignore if */ 
  50.  
  51.   if (typeof Promise !== 'undefined' && isNative(Promise)) { 
  52.  
  53.     let p = Promise.resolve(); 
  54.  
  55.     let logError = err => { 
  56.  
  57.       console.error(err); 
  58.  
  59.     }; 
  60.  
  61.     timerFunc = () => { 
  62.  
  63.       p.then(nextTickHandler).catch(logError); 
  64.  
  65.   
  66.  
  67.       // 在部分 iOS 系統下的 UIWebViews 中,Promise.then 可能并不會被清空,因此我們需要添加額外操作以觸發 
  68.  
  69.       if (isIOS) setTimeout(noop); 
  70.  
  71.     }; 
  72.  
  73.   } else if ( 
  74.  
  75.     typeof MutationObserver !== 'undefined' && 
  76.  
  77.     (isNative(MutationObserver) || 
  78.  
  79.       // PhantomJS and iOS 7.x 
  80.  
  81.       MutationObserver.toString() === '[object MutationObserverConstructor]'
  82.  
  83.   ) { 
  84.  
  85.     // 當 Promise 不可用時候使用 MutationObserver 
  86.  
  87.     // e.g. PhantomJS IE11, iOS7, Android 4.4 
  88.  
  89.     let counter = 1; 
  90.  
  91.     let observer = new MutationObserver(nextTickHandler); 
  92.  
  93.     let textNode = document.createTextNode(String(counter)); 
  94.  
  95.     observer.observe(textNode, { 
  96.  
  97.       characterData: true 
  98.  
  99.     }); 
  100.  
  101.     timerFunc = () => { 
  102.  
  103.       counter = (counter + 1) % 2; 
  104.  
  105.       textNode.data = String(counter); 
  106.  
  107.     }; 
  108.  
  109.   } else { 
  110.  
  111.     // 如果都不存在,則回退使用 setTimeout 
  112.  
  113.     /* istanbul ignore next */ 
  114.  
  115.     timerFunc = () => { 
  116.  
  117.       setTimeout(nextTickHandler, 0); 
  118.  
  119.     }; 
  120.  
  121.   } 
  122.  
  123.   
  124.  
  125.   return function queueNextTick(cb?: Function, ctx?: Object) { 
  126.  
  127.     let _resolve; 
  128.  
  129.     callbacks.push(() => { 
  130.  
  131.       if (cb) { 
  132.  
  133.         try { 
  134.  
  135.           cb.call(ctx); 
  136.  
  137.         } catch (e) { 
  138.  
  139.           handleError(e, ctx, 'nextTick'); 
  140.  
  141.         } 
  142.  
  143.       } else if (_resolve) { 
  144.  
  145.         _resolve(ctx); 
  146.  
  147.       } 
  148.  
  149.     }); 
  150.  
  151.     if (!pending) { 
  152.  
  153.       pending = true
  154.  
  155.       timerFunc(); 
  156.  
  157.     } 
  158.  
  159.   
  160.  
  161.     // 如果沒有傳入回調,則表示以異步方式調用 
  162.  
  163.     if (!cb && typeof Promise !== 'undefined') { 
  164.  
  165.       return new Promise((resolve, reject) => { 
  166.  
  167.         _resolve = resolve; 
  168.  
  169.       }); 
  170.  
  171.     } 
  172.  
  173.   }; 
  174.  
  175. })();  

5. 延伸閱讀

  • 深入淺出 Node.js 全棧架構 – Node.js 事件循環機制詳解與實踐 
責任編輯:龐桂玉 來源: 前端大全
相關推薦

2017-09-14 13:48:20

Vue.js機制應用

2019-10-11 09:00:00

JavaScriptEvent Loop前端

2022-06-29 08:37:03

事件循環JS 語言

2017-07-04 17:55:37

Vue.js插件開發

2018-04-04 10:32:13

前端JavascriptVue.js

2024-04-08 07:28:27

PiniaVue3狀態管理庫

2023-03-29 14:25:08

Vue.js前端框架

2024-05-13 08:04:26

Vue.jsWeb應用程序

2023-04-27 08:23:38

JavaScriptVue.jsMVVC

2024-04-16 07:46:15

Vue3STOMP協議WebSocket

2020-04-26 08:21:43

javascriptVue

2023-04-28 15:20:37

JavaScript事件循環

2022-08-29 18:15:25

Node.js多線程模型

2019-04-01 19:38:28

Vue.jsJavascript前端

2021-05-08 06:14:28

Vue.js片段開發

2010-10-09 10:30:03

JS event

2022-04-04 16:53:56

Vue.js設計框架

2013-10-24 15:23:40

Event Loop

2022-04-01 08:08:27

Vue.js框架命令式

2024-04-07 07:53:12

SpringWeb技術WebSocket
點贊
收藏

51CTO技術棧公眾號

japanese国产精品| 欧美特黄一级视频| 欧美一区在线观看视频| 久久一夜天堂av一区二区三区| 色琪琪综合男人的天堂aⅴ视频| 欧美一级特黄aaaaaa在线看片| 99视频在线看| 日韩在线亚洲| 国产精品不卡视频| 国产xxx69麻豆国语对白| 亚洲熟妇一区二区| av中文在线| 中文亚洲欧美| 精品国产乱码久久久久久蜜臀| 一区二区三区四区免费视频| 草莓视频18免费观看| 久久综合五月婷婷| 亚洲国产中文字幕在线视频综合 | 精品一区二区三区不卡| 亚洲欧美日韩一区二区三区在线| 国产又粗又猛又爽又黄的网站| 最近中文字幕免费在线观看| 亚洲人和日本人hd| 午夜国产精品一区| 欧美人xxxx| 奇米影视首页 狠狠色丁香婷婷久久综合| 五月天婷婷色综合| 欧美v亚洲v综合v国产v仙踪林| 久久精品在这里| 亚洲视频在线观看| 日本免费黄视频| 色av性av丰满av| 日韩精品丝袜美腿| 国产欧美日韩一区二区三区在线观看| 91超碰中文字幕久久精品| 美国黄色一级视频| 538视频在线| 成人毛片视频在线观看| 久久久久久av| 大乳护士喂奶hd| 人狥杂交一区欧美二区| 亚洲毛片网站| 亚洲精品国精品久久99热 | 91精品免费视频| 亚洲国产日韩在线一区| av软件在线观看| 国产成人综合在线| 性色av一区二区三区免费| 亚洲麻豆一区二区三区| 国产在线天堂www网在线观看| 成人午夜看片网址| 97精品国产aⅴ7777| 波多野结衣av在线免费观看| 在线精品亚洲欧美日韩国产| 国产亚洲午夜高清国产拍精品| 国产成人激情视频| 九九热最新地址| 77成人影视| 色综合网站在线| 一本色道久久综合亚洲精品婷婷| av资源免费看| 亚洲一区二区伦理| 深夜福利亚洲导航| 久久发布国产伦子伦精品| 综合久久2o19| 91麻豆蜜桃一区二区三区| 国产精品99久久久久久人| 99国产精品免费| 超碰97久久| 在线免费观看成人短视频| 99re国产视频| 国产综合精品在线| 在线视频成人| 激情久久av一区av二区av三区| 日韩aⅴ视频一区二区三区| 国产精品国产三级国产aⅴ | 最近2019中文字幕第三页视频 | 亚洲精品伊人| 图片区小说区区亚洲影院| 欧美在线激情| 精品人妻aV中文字幕乱码色欲 | 成人欧美一区二区三区在线播放| 国产精品theporn88| 不卡av电影在线| 欧美视频日韩| 这里只有精品视频| 看全色黄大色黄女片18| 亚洲欧美久久精品| 欧美日韩免费区域视频在线观看| 一级做a爰片久久| 亚洲欧洲成人在线| 国产精品自拍三区| 国产精品三级久久久久久电影| 中文字幕第3页| 国产成+人+综合+亚洲欧美| 亚洲国产另类av| 免费看啪啪网站| 最近中文字幕在线免费观看| 欧美日韩日本国产亚洲在线 | 午夜老司机在线观看| 99国产精品视频免费观看| 亚洲在线观看视频网站| 国产裸体美女永久免费无遮挡| 伊人成年综合电影网| 久久精品99国产精品酒店日本| 三上悠亚ssⅰn939无码播放| 91成人福利| 日韩一区二区在线免费观看| 麻豆三级在线观看| 日日av拍夜夜添久久免费| 精品欧美一区二区三区| 久久国产午夜精品理论片最新版本| 免费观看久久久久| 国产日韩欧美a| 欧美激情第一页在线观看| 天天干天天舔天天射| 国产精品乡下勾搭老头1| 国产日韩欧美中文在线播放| 日韩免费av网站| 久久黄色影院| 日韩av免费看| 久久亚洲精品石原莉奈| 久久久久久穴| 国产成人精品在线观看| 精品免费囯产一区二区三区| 亚洲一区日本| 51精品在线观看| 日本学生初尝黑人巨免费视频| 欧美激情麻豆| 久久久久久国产精品三级玉女聊斋| 日本黄色小说视频| 视频亚洲一区二区| 欧美一二三区精品| 人妻精品久久久久中文字幕69| 久久久久久亚洲精品美女| 欧美一区二区三区在线看| 国内av免费观看| 日本99精品| 亚洲福利视频免费观看| 国内精品久久99人妻无码| 免费一区二区| 中文字幕综合在线| caoporn91| 在线成人h网| 91国产美女视频| 亚洲图片欧美日韩| 精彩视频一区二区三区| www日韩av| 欧洲天堂在线观看| 国产精品久久久久影院| 日韩美女爱爱视频| 97成人资源| 欧美二区在线观看| 97精品人人妻人人| 精品99久久| 久久人人爽人人爽爽久久 | 66久久国产| 国内外成人免费激情在线视频| 一区二区三区伦理片| 日韩精品久久久久久久电影99爱| 久久精品2019中文字幕| 好吊操这里只有精品| 日本在线播放一区二区三区| 欧美大片第1页| 日韩精品乱码久久久久久| 欧美中文字幕| 91精品久久久久久久久久久久久久| 国产黄色片免费观看| 91看片淫黄大片一级在线观看| 亚洲午夜在线观看| av中文在线资源库| 欧美精品免费视频| 久久福利小视频| 97久久夜色精品国产| 午夜精品美女自拍福到在线| 怡春院在线视频| av电影在线观看不卡| 亚洲自拍高清视频网站| 青青久草在线| 一二三区精品视频| 国产精品久久a| 美国一区二区| 欧美精品免费播放| 中文字幕欧美人妻精品| 波多野结衣91| 手机在线视频你懂的| 色尼玛亚洲综合影院| 精品久久久三级丝袜| 久久爱一区二区| 日韩精品1区2区3区| 黑人中文字幕一区二区三区| 日本不卡不卡| 欧美网站一区二区| 北条麻妃视频在线| 成人av免费电影网站| 日韩一区二区免费在线电影| 91精品人妻一区二区三区蜜桃欧美| 国产综合精品一区| 欧美精品久久久久久久久久| 亚洲中文一区二区三区| 久久久久免费观看| 久草视频国产在线| 亚洲一区二区三区中文字幕在线观看| 深夜福利亚洲导航| 中文字幕网址在线| 久久久久久综合| 37pao成人国产永久免费视频| 高清精品视频| 欧美激情亚洲综合一区| www.热久久| 亚洲激情成人在线| 成年人午夜视频在线观看| 亚洲日本va中文字幕| 伦伦影院午夜日韩欧美限制| 一本色道久久综合精品婷婷| 国产欧美日韩不卡免费| 日韩欧美xxxx| 国产一区三区在线播放| 青草成人免费视频| 牛牛澡牛牛爽一区二区| 日韩欧美成人免费视频| 丰满少妇一区二区| 首页国产欧美久久| 亚洲第一综合| 国产美女久久| 久久深夜福利免费观看| 国产绳艺sm调教室论坛| 一区二区三区资源| 久久性爱视频网站| 99精品热6080yy久久| 精品国产一区二区三区免费| 欧美a级在线观看| 亚洲美女av网站| 欧美日韩在线视频播放| 中文av一区特黄| 国产成年人视频网站| 一区二区三区午夜视频| 国产精品久久亚洲7777| 麻豆理论在线观看| 亚洲视频在线免费看| 亚洲一级视频在线观看| 亚洲一区视频在线| 国产美女喷水视频| 精品一区二区影视| 97超碰在线人人| 欧美欧美黄在线二区| 国产精品久久久久久久久久三级| bbbbbbbbbbb在线视频| 欧美一区永久视频免费观看| 日本一区二区免费在线观看| 国产日韩综合av| 日韩av自拍偷拍| 99精品视频免费| 午夜精品区一区二区三| 亚洲高清999| 7m精品福利视频导航| 国产在线网站| 欧美一级片在线观看| www.av麻豆| 国产精品福利av| 奇米777第四色| 久久精品国产免费| 国产黄色片免费在线观看| 欧美日韩国产免费观看视频| 91视频婷婷| 成人免费网站www网站高清| 久久99精品久久久久久噜噜| 牛牛热在线视频| 欧美一级二级三级乱码| 无码aⅴ精品一区二区三区| 一区二区三区在线免费播放| 丰满圆润老女人hd| 高清免费成人av| 成人性生交免费看| 亚洲专区在线| 中文字幕日韩精品无码内射| 成人精品中文字幕| 国产视频在线观看一区| 亚洲天堂网站| 国产国语videosex另类| 大黄网站在线观看| 色999日韩欧美国产| 天堂在线观看视频| 欧美一区二区视频免费观看| 五月婷婷激情五月| 五月激情六月综合| 国产97免费视频| 国产精品视频看| 少妇光屁股影院| 成人黄色在线视频| 一二三级黄色片| 免费久久99精品国产| 亚洲自偷自拍熟女另类| 国产精品av久久久久久麻豆网| 亚洲一区精彩视频| 精品国产一区二区三区小蝌蚪 | 久久久精品tv| 中文成人无字幕乱码精品区| 国产盗摄视频一区二区三区| 亚洲欧美自偷自拍另类| 日日骚欧美日韩| 2022亚洲天堂| 国产一级一区二区| 欧美深夜福利视频| 亚洲无毛电影| 日韩成人三级视频| 欧美va亚洲va日韩∨a综合色| 一区精品在线| 色综合咪咪久久网| 午夜欧美性电影| 欧美亚洲高清| 亚洲欧美一区二区原创| 青青草91久久久久久久久| 日本精品免费| 欧美中文一区二区| 亚洲成人午夜在线| 区一区二视频| 夜夜爽99久久国产综合精品女不卡| 欧美亚洲国产激情| 亚洲欧洲精品一区二区| 国产精品久久久久无码av| 一区二区免费在线视频| 婷婷精品进入| 男女裸体影院高潮| 一区二区亚洲精品| 精品视频免费在线播放| 性一交一乱一区二区洋洋av| 男女av免费观看| 日韩精品亚洲一区| 天天干天天操天天做| 精品一区二区三区免费播放| 久久久九九九热| 国产盗摄一区二区三区| 黄色性生活一级片| 欧美专区一区二区三区| 91黄色小网站| 麻豆成人av在线| 99精品视频免费版的特色功能| 国产不卡免费视频| 中文文字幕文字幕高清| 久久一区二区三区四区| 在线免费看视频| 一区二区三区在线视频免费 | 成人高清免费在线播放| 日韩中文字幕网站| 欧美人与性动交α欧美精品济南到| 2020国产精品视频| 久久久久伊人| 国产精品我不卡| 国产欧美日韩精品一区二区免费 | 国内精品美女在线观看| 少妇人妻在线视频| 美女爽到高潮91| youjizz.com日本| 日本一区二区三区dvd视频在线| 极品魔鬼身材女神啪啪精品| 久久久久久毛片| 免费黄色在线网址| 亚洲国产裸拍裸体视频在线观看乱了| 久久精品视频7| 日韩一级高清毛片| 国产视频在线看| 欧美成人黑人xx视频免费观看| 国产高潮在线| 成人国产精品一区二区| 欧美日韩精品一区二区三区在线观看| 国产精品一区专区欧美日韩| 澳门久久精品| 一区二区三区三区在线| aa级大片欧美三级| 欧美精品色视频| 国产日韩欧美综合一区| 久久机热这里只有精品| 在线观看免费一区| 国精产品乱码一区一区三区四区| 伊人久久综合97精品| 97人澡人人添人人爽欧美| 日韩免费在线视频| 成人台湾亚洲精品一区二区| 在线观看一区欧美| 亚洲欧美日韩在线观看a三区| 亚洲一区二区三区四区精品| 久久精品综合网| 成人精品在线看| 日韩欧美一区二区免费| 午夜不卡视频| 国产va免费精品高清在线| 国产96在线亚洲| 免费看黄色a级片| 久久99精品一区二区三区| 99久久精品免费视频| 精品日本高清在线播放| 亚洲黄色在线观看视频| 久久久国产精品亚洲一区| 福利视频亚洲| 欧美12av| 亚洲一区二区免费看| 国产麻豆xxxvideo实拍| 亚洲一区二区欧美激情| 国产黄色片av|