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

異步單例模式之不一樣的單例模式

開發 前端
創建實例需要一定的時間,創建期間,交出執行權,創建完畢后,拿回執行權,返回結果。

[[422320]]

本文轉載自微信公眾號「云的程序世界」,作者云的世界。轉載本文請聯系云的程序世界公眾號。

前言

單例模式大家都知道,異步單例又為何物。

異步單例:

創建實例需要一定的時間,創建期間,交出執行權,創建完畢后,拿回執行權,返回結果。

有人可能會吐槽,就這,其他方案分分鐘搞定。沒錯,沒有誰不可被替代。

這里主要表達的是一種編程思想,其能改變代碼風格, 特定情況下漂亮的解決問題。多一種手段,多一種選擇。

先一起來看一個栗子:

asyncInsCreator延時2秒創建一個對象;

getAsyncIns 封裝異步對象獲取過程;

我們多次調用 getAsyncIns, 得到同一個對象。

  1. async function asyncInsCreator() { 
  2.     await delay(2000).run(); 
  3.     return new Object(); 
  4.  
  5. function getAsyncIns() { 
  6.     return factory(asyncInsCreator); 
  7.  
  8. ; (async function test() { 
  9.     try {   
  10.         const [ins1, ins2, ins3] = await Promise.all([ 
  11.             getAsyncIns(), 
  12.             getAsyncIns(), 
  13.             getAsyncIns() 
  14.         ]); 
  15.  
  16.         console.log("ins1:", ins1);  // ins1: {} 
  17.         console.log("ins1===ins2", ins1 === ins2); // ins1===ins2 true 
  18.         console.log("ins2===ins3", ins2 === ins3); // ins2===ins3 true 
  19.         console.log("ins3=== ins1", ins3 === ins1); // ins3=== ins1 true 
  20.     } catch (err) { 
  21.         console.log("err", err); 
  22.     } 
  23. })(); 

適用場景

異步單例

比如初始化socket.io客戶端, indexedDB等等

僅僅一次的情況

舉一個例子,我們可以注冊多個 load事件

  1. window.addEventListener("load"function () { 
  2.      // other code 
  3.      console.log("load 1"); 
  4. }); 
  5.  
  6. window.addEventListener("load"function () { 
  7.      // other code 
  8.      console.log("load 2"); 
  9. ); 

這要是換做React或者Vue,你先得訂閱還得取消訂閱,顯得麻煩,當然你可以利用訂閱發布思想再包裝一層:

如果換成如下,是不是賞心悅目:

  1. await loaded(); 
  2. // TODO::   

你肯定說,這個我會:

  1. function loaded() { 
  2.        return new Promise((resove, reject) => { 
  3.            window.addEventListener("load", resove) 
  4.        }); 
  5.    } 

我給你一段測試代碼:

下面只會輸出 loaded 1,不會輸出loaded 2。

至于原因:load事件只會觸發一次。

  1. function loaded() { 
  2.     return new Promise((resolve, reject) => { 
  3.         window.addEventListener("load", ()=> resolve(null)); 
  4.     }); 
  5.  
  6. async function test() { 
  7.     await loaded(); 
  8.     console.log("loaded 1"); 
  9.      
  10.     setTimeout(async () => { 
  11.         await loaded(); 
  12.         console.log("loaded 2"); 
  13.     }, 1000) 
  14.  
  15. est(); 

到這里,我們的異步單例就可以秀一把,雖然他本意不是干這個,但他可以,因為他滿足僅僅一次的條件。

我們看看使用異步單例模式的代碼:

loaded 1 與 loaded 2 都如期到來。

  1. const factory = asyncFactory(); 
  2.  
  3. function asyncInsCreator() { 
  4.     return new Promise((resove, reject) => { 
  5.         window.addEventListener("load", ) 
  6.     }); 
  7.  
  8. function loaded() { 
  9.     return factory(asyncInsCreator) 
  10.  
  11. async function test() { 
  12.     await loaded(); 
  13.     console.log("loaded 1");  // loaded 1 
  14.  
  15.     setTimeout(async () => { 
  16.         await loaded(); 
  17.         console.log("loaded 2"); // loaded 2 
  18.     }, 1000) 
  19.  
  20. test(); 

實現思路

狀態

實例創建,其實也就只有簡簡單單的兩種狀態:

  1. 創建中
  2. 創建完畢

難點在于,創建中的時候,又有新的請求來獲取實例。

那么我們就需要一個隊列或者數組來維護這些請求隊列,等待實例創建完畢,再通知請求方。

如果實例化已經完畢,那么之后就直接返回實例就好了。

變量

我們這里就需要三個變量:

  1. instance 存儲已經創建完畢的實例
  2. initializing 是否創建中
  3. requests 來保存哪些處于創建中,發過來的請求

工具方法

delay:

延時一定時間調用指定的函數。

用于后面的超時,和模擬延時。

  1. export function delay(delay: number = 5000, fn = () => { }, context = null) { 
  2.     let ticket = null
  3.     return { 
  4.         run(...args: any[]) { 
  5.             return new Promise((resolve, reject) => { 
  6.                 ticket = setTimeout(async () => { 
  7.                     try { 
  8.                         const res = await fn.apply(context, args); 
  9.                         resolve(res); 
  10.                     } catch (err) { 
  11.                         reject(err); 
  12.                     } 
  13.                 }, delay); 
  14.             }); 
  15.         }, 
  16.         cancel: () => { 
  17.             clearTimeout(ticket); 
  18.         } 
  19.     }; 
  20. }; 

基礎版本

實現代碼

注意點:

1.instance !== undefined這個作為判斷是否實例化,也就是說可以是null, 僅僅一次的場景下使用,最適合不過了。

這里也是一個局限,如果就是返回undefined呢, 我保持沉默。

2.有人可能會吐槽我,你之前還說過 undefined不可靠,我微微一笑,你覺得迷人嗎?

失敗之后 initializing = false這個意圖,就是某次初始化失敗時,會通知之前的全部請求,已失敗。

之后的請求,還會嘗試初始化。

  1. import { delay } from "../util"
  2.  
  3. function asyncFactory() { 
  4.     let requests = []; 
  5.     let instance; 
  6.     let initializing = false
  7.  
  8.     return function initiator(fn: (...args: any) => Promise<any>) { 
  9.          // 實例已經實例化過了 
  10.          if (instance !== undefined){ 
  11.             return Promise.resolve(instance); 
  12.         } 
  13.         // 初始化中 
  14.         if (initializing) { 
  15.             return new Promise((resolve, reject) => { 
  16.                 // 保存請求 
  17.                 requests.push({ 
  18.                     resolve, 
  19.                     reject 
  20.                 }); 
  21.             }) 
  22.         } 
  23.         initializing = true
  24.         return new Promise((resolve, reject) => { 
  25.             // 保存請求 
  26.             requests.push({ 
  27.                 resolve, 
  28.                 reject 
  29.             }); 
  30.  
  31.             fn() 
  32.                 .then(result => { 
  33.                     instance = result; 
  34.                     initializing = false
  35.                     processRequests('resolve', instance); 
  36.                 }) 
  37.                 .catch(error => { 
  38.                     initializing = false
  39.                     processRequests('reject', error); 
  40.                 }); 
  41.         }); 
  42.     } 
  43.     function processRequests(type: "resolve" | "reject", value: any) { 
  44.         // 挨個resolve 
  45.         requests.forEach(q => { 
  46.             q[type](value "type"); 
  47.         }); 
  48.         // 置空請求,之后直接用instance 
  49.         requests = []; 
  50.     } 

測試代碼

  1. const factory = asyncFactory(); 
  2.  
  3. async function asyncInsCreator() { 
  4.     await delay(2000).run(); 
  5.     return new Object(); 
  6.  
  7. function getAsyncIns() { 
  8.     return factory(asyncInsCreator); 
  9.  
  10. ; (async function test() { 
  11.     try {   
  12.  
  13.         const [ins1, ins2, ins3] = await Promise.all([ 
  14.             getAsyncIns(), 
  15.             getAsyncIns(), 
  16.             getAsyncIns() 
  17.         ]); 
  18.  
  19.         console.log("ins1:", ins1);  // ins1: {} 
  20.         console.log("ins1===ins2", ins1 === ins2); // ins1===ins2 true 
  21.         console.log("ins2===ins3", ins2 === ins3); // ins2===ins3 true 
  22.         console.log("ins3=== ins1", ins3 === ins1); // ins3=== ins1 true 
  23.     } catch (err) { 
  24.         console.log("err", err); 
  25.     } 
  26.  
  27. })(); 

存在的問題:

沒法傳參啊,沒法設置this的上下文啊。

傳遞參數版本

實現思路:

  1. 增加參數 context 以及 args參數
  2. Function.prototype.appy

實現代碼

  1. import { delay } from "../util"
  2.  
  3. interface AVFunction<T = unknown> { 
  4.     (value: T): void 
  5.  
  6. function asyncFactory<R = unknown, RR = unknown>() { 
  7.     let requests: { reject: AVFunction<RR>, resolve: AVFunction<R> }[] = []; 
  8.     let instance: R; 
  9.     let initializing = false
  10.  
  11.     return function initiator(fn: (...args: any) => Promise<R>,  
  12.     context: unknown, ...args: unknown[]): Promise<R> { 
  13.         // 實例已經實例化過了 
  14.         if (instance !== undefined){ 
  15.             return Promise.resolve(instance); 
  16.         } 
  17.         // 初始化中 
  18.         if (initializing) { 
  19.             return new Promise((resolve, reject) => { 
  20.                 requests.push({ 
  21.                     resolve, 
  22.                     reject 
  23.                 }) 
  24.             }) 
  25.         } 
  26.         initializing = true 
  27.         return new Promise((resolve, reject) => { 
  28.             requests.push({ 
  29.                 resolve, 
  30.                 reject 
  31.             }) 
  32.  
  33.             fn.apply(context, args) 
  34.                 .then(res => { 
  35.                     instance = res; 
  36.                     initializing = false
  37.                     processRequests('resolve', instance); 
  38.                 }) 
  39.                 .catch(error => { 
  40.                     initializing = false
  41.                     processRequests('reject', error); 
  42.                 }) 
  43.         }) 
  44.     } 
  45.  
  46.     function processRequests(type: "resolve" | "reject", value: any) { 
  47.         // 挨個resolve 
  48.         requests.forEach(q => { 
  49.             q[type](value "type"); 
  50.         }); 
  51.         // 置空請求,之后直接用instance 
  52.         requests = []; 
  53.     } 

測試代碼

  1. interface RES { 
  2.     p1: number 
  3.  
  4. const factory = asyncFactory<RES>(); 
  5.  
  6. async function asyncInsCreator(opitons: unknown = {}) { 
  7.     await delay(2000).run(); 
  8.     console.log("context.name", this.name); 
  9.     const result = new Object(opitons) as RES; 
  10.     return result; 
  11.  
  12. function getAsyncIns(context: unknown, options: unknown = {}) { 
  13.     return factory(asyncInsCreator, context, options); 
  14.  
  15. ; (async function test() { 
  16.  
  17.     try { 
  18.         const context = { 
  19.             name"context" 
  20.         }; 
  21.  
  22.         const [ins1, ins2, ins3] = await Promise.all([ 
  23.             getAsyncIns(context, { p1: 1 }), 
  24.             getAsyncIns(context, { p1: 2 }), 
  25.             getAsyncIns(context, { p1: 3 }) 
  26.         ]); 
  27.  
  28.         console.log("ins1:", ins1, ins1.p1); 
  29.         console.log("ins1=== ins2", ins1 === ins2); 
  30.         console.log("ins2=== ins3", ins2 === ins3); 
  31.         console.log("ins3=== ins1", ins3 === ins1); 
  32.     } catch (err) { 
  33.         console.log("err", err); 
  34.     } 
  35.  
  36. })(); 

存在的問題

看似完美,要是超時了,怎么辦呢?

想到這個問題的人,品論區發文,我給你們點贊。

超時版本

這里就需要借用我們的工具方法delay:

  • 如果超時沒有成功,通知所有請求失敗。
  • 反之,通知所有請求成功。

實現代碼

  1. import { delay } from "../util"
  2.  
  3. interface AVFunction<T = unknown> { 
  4.     (value: T): void 
  5.  
  6. function asyncFactory<R = unknown, RR = unknown>(timeout: number = 5 * 1000) { 
  7.     let requests: { reject: AVFunction<RR>, resolve: AVFunction<R> }[] = []; 
  8.     let instance: R; 
  9.     let initializing = false
  10.  
  11.     return function initiator(fn: (...args: any) => Promise<R>, context: unknown, ...args: unknown[]): Promise<R> { 
  12.  
  13.         // 實例已經實例化過了 
  14.         if (instance !== undefined){ 
  15.             return Promise.resolve(instance); 
  16.         } 
  17.  
  18.         // 初始化中 
  19.         if (initializing) { 
  20.             return new Promise((resolve, reject) => { 
  21.                 requests.push({ 
  22.                     resolve, 
  23.                     reject 
  24.                 }) 
  25.             }) 
  26.         } 
  27.  
  28.         initializing = true 
  29.         return new Promise((resolve, reject) => { 
  30.  
  31.             requests.push({ 
  32.                 resolve, 
  33.                 reject 
  34.             }) 
  35.  
  36.             const { run, cancel } = delay(timeout); 
  37.  
  38.             run().then(() => { 
  39.                 const error = new Error("操作超時"); 
  40.                 processRequests("reject", error); 
  41.             }); 
  42.  
  43.             fn.apply(context, args) 
  44.                 .then(res => { 
  45.                     // 初始化成功 
  46.                     cancel(); 
  47.                     instance = res; 
  48.                     initializing = false
  49.                     processRequests('resolve', instance); 
  50.                 }) 
  51.                 .catch(error => { 
  52.                     // 初始化失敗 
  53.                     cancel(); 
  54.                     initializing = false
  55.                     processRequests('reject', error); 
  56.                 }) 
  57.         }) 
  58.     } 
  59.  
  60.     function processRequests(type: "resolve" | "reject", value: any) { 
  61.         // 挨個resolve 
  62.         requests.forEach(q => { 
  63.             q[type](value "type"); 
  64.         }); 
  65.         // 置空請求,之后直接用instance 
  66.         requests = []; 
  67.     } 
  68.  
  69. interface RES { 
  70.     p1: number 
  71. const factory = asyncFactory<RES>(); 
  72.  
  73. async function asyncInsCreator(opitons: unknown = {}) { 
  74.     await delay(1000).run(); 
  75.     console.log("context.name", this.name); 
  76.     const result = new Object(opitons) as RES; 
  77.     return result; 
  78.  
  79. function getAsyncIns(context: unknown, options: unknown = {}) { 
  80.     return factory(asyncInsCreator, context, options); 
  81. ; (async function test() { 
  82.  
  83.     try { 
  84.         const context = { 
  85.             name"context" 
  86.         }; 
  87.  
  88.         const [instance1, instance2, instance3] = await Promise.all([ 
  89.             getAsyncIns(context, { p1: 1 }), 
  90.             getAsyncIns(context, { p1: 2 }), 
  91.             getAsyncIns(context, { p1: 3 }) 
  92.         ]); 
  93.  
  94.         console.log("instance1:", instance1, instance1.p1); 
  95.         console.log("instance1=== instance2", instance1 === instance2); 
  96.         console.log("instance2=== instance3", instance2 === instance3); 
  97.         console.log("instance3=== instance1", instance3 === instance1); 
  98.     } catch (err) { 
  99.         console.log("err", err); 
  100.     } 
  101. })(); 

測試代碼

當把asyncInsCreator的 delay(1000)修改為 delay(6000)的時候,創建所以的事件6000ms大于 asyncFactory默認的5000ms,就會拋出下面的異常。

  1. err Error: 操作超時 
  2.     at c:\projects-github\juejinBlogs\異步單例\queue\args_timeout.ts:40:31 
  1. interface RES { 
  2.     p1: number 
  3.  
  4. const factory = asyncFactory<RES>(); 
  5.  
  6.  
  7. async function asyncInsCreator(opitons: unknown = {}) { 
  8.     await delay(1000).run(); 
  9.     console.log("context.name", this.name); 
  10.     const result = new Object(opitons) as RES; 
  11.     return result; 
  12.  
  13. function getAsyncIns(context: unknown, options: unknown = {}) { 
  14.     return factory(asyncInsCreator, context, options); 
  15.  
  16. ; (async function test() { 
  17.     try { 
  18.         const context = { 
  19.             name"context" 
  20.         }; 
  21.         const [ins1, ins2, ins3] = await Promise.all([ 
  22.             getAsyncIns(context, { p1: 1 }), 
  23.             getAsyncIns(context, { p1: 2 }), 
  24.             getAsyncIns(context, { p1: 3 }) 
  25.         ]); 
  26.  
  27.         console.log("ins1:", ins1, ins1.p1); 
  28.         console.log("ins1=== ins2", ins1 === ins2); 
  29.         console.log("ins2=== ins3", ins2 === ins3); 
  30.         console.log("ins3=== ins1", ins3 === ins1); 
  31.     } catch (err) { 
  32.         console.log("err", err); 
  33.     } 
  34. })(); 

存在的問題

存在的問題:

  1. 拋出了的Error new Error("操作超時")我們簡單粗暴的拋出了這個異常,當外圍的try/catch捕獲后,還沒法區別這個錯誤的來源。我們可以再封住一個AsyncFactoryError,或者 asyncInsCreator 拋出特定一定,交給try/catch 自身去識別。
  2. 沒有判斷參數 fn如果不是一個有效的函數,fn執行后是不是一個返回Promise。

是不是一個有效的函數好判斷。

執行后是不是返回一個Promise, 借巨人p-is-promise[1]肩膀一靠。

  1. // 核心代碼 
  2. function isPromise(value) { 
  3.    return value instanceof Promise || 
  4.     ( 
  5.      isObject(value) && 
  6.      typeof value.then === 'function' && 
  7.      typeof value.catch === 'function' 
  8.     ); 

存在問題,你就不解決了嗎?不解決,等你來動手。

基于訂閱發布模式的版本

這里是實現的另外一種思路, 利用訂閱發布者。

要點

通過在Promise監聽EventEmitter事件, 這里因為只需要監聽一次,once閃亮登場。

  1. new Promise((resolve, reject) => { 
  2.     emitter.once("initialized", () => { 
  3.         resolve(instance); 
  4.     }); 
  5.     emitter.once("error", (error) => { 
  6.         reject(error); 
  7.     }); 
  8. }); 

實現代碼

這里就實現一個最基礎版本,至于帶上下文,參數,超時的版本,大家可以嘗試自己實現。

  1. import { EventEmitter } from "events"
  2. import { delay } from "./util"
  3.  
  4. function asyncFactory<R = any>() { 
  5.     let emitter = new EventEmitter(); 
  6.     let instance: any = null
  7.     let initializing = false
  8.  
  9.     return function getAsyncInstance(factory: () => Promise<R>): Promise<R> { 
  10.         // 已初始化完畢 
  11.         if (instance !== undefined){ 
  12.             return Promise.resolve(instance); 
  13.         } 
  14.         // 初始化中 
  15.         if (initializing === true) { 
  16.             return new Promise((resolve, reject) => { 
  17.                 emitter.once("initialized", () => { 
  18.                     resolve(instance); 
  19.                 }); 
  20.                 emitter.once("error", (error) => { 
  21.                     reject(error); 
  22.                 }); 
  23.             }); 
  24.         } 
  25.  
  26.         initializing = true
  27.         return new Promise((resolve, reject) => { 
  28.             emitter.once("initialized", () => { 
  29.                 resolve(instance); 
  30.             }); 
  31.             emitter.once("error", (error) => { 
  32.                 reject(error); 
  33.             }); 
  34.             factory() 
  35.                 .then(ins => { 
  36.                     instance = ins; 
  37.                     initializing = false
  38.                     emitter.emit("initialized"); 
  39.                     emitter = null
  40.                 }) 
  41.                 .catch((error) => { 
  42.                     initializing = false
  43.                     emitter.emit("error", error); 
  44.                 }); 
  45.         }) 
  46.     } 

總結

異步單例不多見,這里要表達的是一種思想,把基于事件的編程,變為基于Promise的編程。

這里其實還涉及一些設計模式, 學以致用,投入實際代碼中,解決問題,帶來收益,這才是我們追求的。

async-init[2]

Is it impossible to create a reliable async singleton pattern in JavaScript?[3]

Creating an async singletone in javascript[4]

參考資料

[1]p-is-promise: https://www.npmjs.com/package/p-is-promise

[2]async-init: https://github.com/ert78gb/async-init

[3]Is it impossible to create a reliable async singleton pattern in JavaScript?: https://stackoverflow.com/questions/58919867/is-it-impossible-to-create-a-reliable-async-singleton-pattern-in-javascript

[4]Creating an async singletone in javascript: https://stackoverflow.com/questions/59612076/creating-an-async-singletone-in-javascript

 

責任編輯:武曉燕 來源: 云的程序世界
相關推薦

2016-03-28 10:23:11

Android設計單例

2023-06-05 07:55:31

2022-06-07 08:55:04

Golang單例模式語言

2021-02-01 10:01:58

設計模式 Java單例模式

2021-03-02 08:50:31

設計單例模式

2015-09-06 11:07:52

C++設計模式單例模式

2022-09-29 08:39:37

架構

2013-11-26 16:20:26

Android設計模式

2022-02-06 22:30:36

前端設計模式

2024-02-04 12:04:17

2011-03-16 10:13:31

java單例模式

2021-02-07 23:58:10

單例模式對象

2024-03-06 13:19:19

工廠模式Python函數

2023-11-21 21:39:38

單例模式音頻管理器

2011-06-28 15:18:45

Qt 單例模式

2016-10-09 09:37:49

javascript單例模式

2012-12-20 10:17:32

IT運維

2012-03-07 17:24:10

戴爾咨詢

2019-06-11 09:50:07

SparkBroadcast代碼

2021-08-11 17:22:11

設計模式單例
點贊
收藏

51CTO技術棧公眾號

欧洲一级精品| 欧美老熟妇一区二区三区| 日韩伦理在线| 国产日韩欧美综合一区| 亚洲在线视频福利| 久久久免费观看| 亚洲另类第一页| 日本一本在线免费福利| 久久久国产精品不卡| 91老司机精品视频| av黄色在线播放| 亚洲成人av| 亚洲欧美日韩精品久久亚洲区 | 爱情岛论坛亚洲入口| 97超碰人人干| 亚洲色图88| 亚洲欧美一区二区三区情侣bbw| 亚洲第一天堂久久| 亚洲天堂资源| 一区二区三区免费网站| 日韩精品无码一区二区三区| 亚洲AV无码国产精品午夜字幕 | 丁香婷婷在线观看| 成人在线综合网| 国产日韩欧美电影在线观看| 欧美一级片免费在线观看| 天天插综合网| 亚洲欧美成人网| 国产污在线观看| av在线亚洲一区| 欧美色图免费看| 国产真实乱子伦| 国产盗摄在线视频网站| 中文字幕在线不卡| 日韩精品电影网站| 欧美一区二区三区少妇| 成人美女视频在线观看| 91黄色精品| 国产又粗又长又大视频| 无码人妻熟妇av又粗又大| 自拍欧美一区| 亚洲精品久久久久久久久久久久| 在线观看一区二区三区视频| 在线视频成人| 欧美精品久久天天躁| 99久久国产宗和精品1上映| 9999在线视频| 亚洲成人在线免费| 又大又硬又爽免费视频| 影音先锋中文在线视频| 亚洲免费av网站| www.黄色网址.com| 成人日批视频| 亚洲三级免费观看| 午夜探花在线观看| 91精品久久久| 一区二区三区久久| 黄色一级片国产| 色帝国亚洲欧美在线| 亚洲精品久久久蜜桃| 久久久久亚洲av无码专区喷水| 中文字幕在线观看日本| 国产精品久久久久永久免费观看| 亚洲国产精品久久久久婷婷老年 | 欧美另类69精品久久久久9999| 国产视频123区| 色综合久久网| 美乳少妇欧美精品| 久操免费在线视频| 日韩一级免费| 国产精品igao视频| 亚洲最新av网站| 国产精品456露脸| 成人情视频高清免费观看电影| 丰满人妻一区二区三区免费| 99久久国产综合色|国产精品| 狼狼综合久久久久综合网| 日韩福利小视频| 精品久久久久一区二区三区| 国产精品亚洲第一| 国产区欧美区日韩区| 你懂的在线网址| 国产精品久久网站| 97久久国产亚洲精品超碰热| 日本乱码一区二区三区不卡| 欧美性猛交一区二区三区精品| 精品综合久久久久| 老牛国内精品亚洲成av人片| 国产一区二区日韩| 少妇被躁爽到高潮无码文| 伊人久久婷婷| 国产精品亚洲视频在线观看| 亚洲国产精品无码久久| 国产欧美精品一区二区色综合| youjizz.com亚洲| 高清视频在线观看三级| 欧美日韩一区二区三区高清| yjizz视频| 欧美一二区在线观看| 欧美国产精品人人做人人爱| 亚洲GV成人无码久久精品| 日本伊人午夜精品| 国产伦精品一区二区三区照片91| 国产在线黄色| 亚洲va欧美va人人爽午夜| 欧美三级理论片| 女一区二区三区| 久久久国产成人精品| 欧美videossex极品| 国产在线播放一区| 日本不卡免费新一二三区| 国产探花在线观看| 欧美精品777| 亚洲人成人无码网www国产 | 国产精品美女久久久久久久| a级免费在线观看| 国产精品66| 亚洲精品一区二区网址| 久久久久久久久久91| 麻豆国产精品777777在线| 玛丽玛丽电影原版免费观看1977 | 黑人一区二区| 国产欧美日韩免费| 蜜桃成人在线视频| 精品久久久久久| 日本中文字幕精品| 婷婷久久综合| 国产精品丝袜一区二区三区| 可以在线观看的av| 欧美性xxxxx极品娇小| 在线播放第一页| 欧美一区二区三区久久精品茉莉花| 国产精品第10页| 巨骚激情综合| 91久久香蕉国产日韩欧美9色| 精品人妻一区二区三区日产| 国产精品大片| 97超级碰碰| 91国内在线| 欧美一区二区免费视频| 日本在线一级片| 国产在线播放一区三区四| 一级日韩一区在线观看| 欧美视频第一| 国产精品久在线观看| 少妇喷水在线观看| 一区二区三区欧美在线观看| 四虎1515hh.com| 国产精品成人一区二区不卡| 国产乱肥老妇国产一区二| 国产黄色在线播放| 91福利精品视频| 亚洲黄色免费视频| 日本亚洲最大的色成网站www| 日韩精品一区二区三区丰满| 992tv国产精品成人影院| 亚洲女同精品视频| 亚洲大尺度在线观看| 国产天堂亚洲国产碰碰| 日本中文字幕高清| 婷婷六月综合| 成人欧美一区二区| 蜜桃视频动漫在线播放| 亚洲跨种族黑人xxx| 中文字幕69页| 国产精品嫩草影院av蜜臀| 日韩av在线中文| 91精品国产自产在线观看永久∴| 91亚色免费| 一区二区在线观看免费视频播放| 成人手机视频在线| 国产精品国产三级在线观看| 久久99热这里只有精品国产| 亚洲精品网站在线| 黄色成人在线免费| 免费看裸体网站| 国产一区二区三区在线观看精品| 青青青在线观看视频| 全国精品免费看| 国产精品中文在线| 在线免费观看的av| 日韩av一区二区在线| 五月婷婷六月婷婷| 亚洲欧美一区二区久久 | 丁香亚洲综合激情啪啪综合| 久久黄色片视频| 欧美一区二区三区高清视频| 91精品久久久久久久久久久久久| 美洲精品一卡2卡三卡4卡四卡| 亚洲精品久久久久中文字幕二区| 国产99久久久久久免费看| 亚洲色图在线播放| 国产艳俗歌舞表演hd| 麻豆成人91精品二区三区| 日韩精品在线视频免费观看| 国产毛片一区二区三区| 97碰碰视频| 欧美xxxx做受欧美护士| 欧美另类高清videos| 久草福利在线| 欧美不卡一区二区| 欧美激情一区二区三区免费观看| 亚洲一区二区三区激情| 五月婷婷欧美激情| 成人app下载| 激情黄色小视频| 西西裸体人体做爰大胆久久久| 中文字幕不卡每日更新1区2区| 日韩三级av| 5g国产欧美日韩视频| 伊人久久高清| 97碰碰碰免费色视频| 成年人网站在线| 国产亚洲欧洲黄色| 偷拍25位美女撒尿视频在线观看| 制服丝袜在线91| 波多野结衣一区二区在线| 亚洲国产sm捆绑调教视频 | 国产精品美女av| 高清在线视频不卡| 九九九久久国产免费| 在线a人片免费观看视频| 日韩精品高清在线观看| 亚洲第九十九页| 欧美一级电影网站| 一卡二卡在线视频| 欧美视频一区二区三区四区| 国产精品乱子伦| 亚洲高清不卡在线观看| 老湿机69福利| 自拍偷拍亚洲综合| av在线免费播放网址| av动漫在线观看| 韩国女主播一区二区三区| 成人xxxx视频| 99久久er| 国产精品电影在线观看| av电影一区| 1769国产精品| 九色porny丨国产首页在线| 欧美日韩成人在线观看| 综合图区亚洲| 麻豆一区二区在线观看| 日本在线观看免费| 日韩在线视频中文字幕| www视频在线观看免费| 亚洲亚裔videos黑人hd| 韩日视频在线| 亚洲午夜久久久影院| 国产资源在线播放| 在线观看国产精品91| 成年午夜在线| 北条麻妃在线一区二区| 毛片在线看网站| 久久国产精品久久国产精品| 羞羞网站在线看| 久久久久久久久久久人体| 国产福利在线免费观看| 2021国产精品视频| 奇米777日韩| 国产精品亚洲一区二区三区| 99久久999| 成人动漫视频在线观看完整版| 91综合久久爱com| 久久久精彩视频| 日韩在线精品| 成年丰满熟妇午夜免费视频| 午夜视频精品| 波多野结衣乳巨码无在线| 丝袜亚洲精品中文字幕一区| 日本激情视频在线播放| 国产美女在线精品| 国产一卡二卡三卡四卡| www成人在线观看| 日本理论中文字幕| 亚洲欧美日韩一区二区 | 狠狠久久五月精品中文字幕| 中文字幕免费观看| 欧美丰满少妇xxxxx高潮对白| 午夜精品久久久久久久99老熟妇| 亚洲精品美女网站| av午夜在线| 欧美激情喷水视频| 免费福利视频一区二区三区| 国产精品视频免费在线| 伊人久久影院| 色一情一区二区三区四区| 自拍偷拍欧美| 成人亚洲视频在线观看| 国产精品夜夜爽| 爱爱免费小视频| 亚洲欧洲综合另类| 欧美超碰在线观看| 日韩午夜在线影院| 狠狠狠综合7777久夜色撩人| 久久99久国产精品黄毛片入口| 亚洲欧美se| 91嫩草国产在线观看| 国内精品视频在线观看 | 日韩av一区二| wwwxx日本| 国产精品久久久久久久久免费桃花| 久久精品视频8| 欧美色区777第一页| 欧美一区二区三区激情| 久久精品国产成人精品| 东京一区二区| 成人免费在线一区二区三区| 久久高清免费| 日本a级片免费观看| 国产 日韩 欧美大片| 亚洲精品成人av久久| 黄色精品在线看| 亚洲av无码国产精品久久不卡| 自拍偷拍亚洲区| 新片速递亚洲合集欧美合集| 国产精品亚洲综合| 欧美成人国产| 在线视频日韩欧美| 亚洲国产精品ⅴa在线观看| 久久艹免费视频| 精品成人私密视频| 国产激情小视频在线| 国产精品稀缺呦系列在线 | 欧美h视频在线观看| 视频一区二区三区在线| 亚洲男人在线天堂| 亚洲国产成人精品视频| 亚洲精品字幕在线| 九九视频这里只有精品| 国产精品日本一区二区不卡视频| 台湾成人av| 青青青伊人色综合久久| 日本xxxxxxxxx18| 欧美特级www| 亚洲欧美日韩免费| 国产69久久精品成人| 国产精品毛片视频| cao在线观看| av色综合久久天堂av综合| 国产性一乱一性一伧一色| 日韩一区二区影院| 午夜羞羞小视频在线观看| 亚洲va欧美va国产综合久久| 国产精品97| 三日本三级少妇三级99| 亚洲免费资源在线播放| 国产a级免费视频| 欧美激情在线有限公司| 国产精品网在线观看| 久久综合九色综合88i| 9人人澡人人爽人人精品| 国产成人无码一区二区三区在线| 亚洲国产日韩精品在线| 亚洲欧美se| 亚洲视频欧美在线| 国产在线不卡一卡二卡三卡四卡| 国产盗摄一区二区三区在线| 欧美成人欧美edvon| 77thz桃花论族在线观看| 国产一区不卡在线观看| 国产精品久久久亚洲一区| 久久久无码人妻精品一区| 在线免费视频一区二区| 中文字幕在线视频区| 2014亚洲精品| 亚洲自啪免费| 国产探花视频在线播放| 欧美一区二区三区视频在线| av第一福利在线导航| 久久久久一区二区| 水莓100在线视频| 精品999在线播放| 欧美成人h版| 国产系列第一页| 成人ar影院免费观看视频| 天堂网视频在线| 久久伊人免费视频| 凹凸av导航大全精品| 日韩精品无码一区二区三区免费| 国产精品二三区| 人妻中文字幕一区| 国产精品极品美女粉嫩高清在线| 一区二区中文字| 男人天堂av电影| 欧美一级专区免费大片| 在线视频cao| 国产三级中文字幕| 久久综合久久综合久久| 国产麻豆一精品一男同| 欧美一级高清免费| 一区二区三区四区日韩| 国产成人无码一区二区在线观看| 91.成人天堂一区| 一个人看的www视频在线免费观看| 中文字幕一区二区三区最新 | 欧美亚洲一区二区三区| av成人免费网站| 亚洲桃花岛网站| 成人直播在线观看|