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

【前端】從小白視角上手Promise、Async/Await和手撕代碼

開發 前端
對于前端新手而言,Promise是一件比較困擾學習的事情,需要理解的細節比較多。對于前端面試而言,Promise是面試官最常問的問題,特別是手撕源碼。眾所周知,JavaScript語言執行環境是“單線程”。

[[400035]]

寫在前面

對于前端新手而言,Promise是一件比較困擾學習的事情,需要理解的細節比較多。對于前端面試而言,Promise是面試官最常問的問題,特別是手撕源碼。眾所周知,JavaScript語言執行環境是“單線程”。

單線程,就是指一次只能完成一件任務,如果有多個任務就必須排隊等候,前面一個任務完成,再執行后面一個任務。這種“單線程”模式執行效率較低,任務耗時長。

為了解決這個問題,就有了異步模式,也叫異步編程。

一、異步編程

所謂"異步",簡單說就是一個任務分成兩段,先執行第一段,然后轉而執行其他任務,當第一段有了執行結果之后,再回過頭執行第二段。

JavaScript采用異步編程原因有兩點:

  • JavaScript是單線程。
  • 為了提高CPU的利用率。

在提高CPU的利用率的同時也提高了開發難度,尤其是在代碼的可讀性上。

那么異步存在的場景有:

  • fs 文件操作
  1. require("fs").readFile("./index.html",(err,data)=>{}) 
  • 數據庫操作
  • AJAX
  1. $.get("/user",(data)=>{}) 

定時器

  1. setTimeout(()=>{},2000) 

二、Promise是什么

Promise理解

(1) 抽象表達

  • Promise 是一門新的技術(es6規范)
  • Promise是js中進行異步編程的新解決方案

(2) 具體表達

  • 從語法上說:Promise是一個構造函數
  • 從功能上說:Promise對象是用來封裝一個異步操作并可以獲取其成功/失敗的結果值

為什么要使用Promise

(1) 指定回調函數的方式更加靈活

  • promise:啟動異步任務=>返回promise對象=>給promise對象綁定回調函數

(2) 支持鏈式調用方式,可以解決回調地獄問題

  • 什么是回調地獄?

回調地獄就是回調函數嵌套使用,外部回調函數異步執行的結果是嵌套的回調執行的條件

  • 回調地獄的缺點

不便于閱讀

不便于異常處理

解決方法

Promise的狀態

  1. Promise必須擁有三種狀態:pending、rejected、resolved
  2. 如果Promise的狀態是pending時,它可以變成成功fulfilled或失敗rejected
  3. 如果promise是成功狀態,則它不能轉換為任何狀態,而且需要一個成功的值,并且這個值不能改變
  4. 如果promise是失敗狀態,則它不能轉換成任何狀態,而且需要一個失敗的原因,并且這個值不能改變

Promise的狀態改變

pending未決定的,指的是實例狀態內置的屬性

(1)pending變為resolved/fullfilled

(2)pending變為rejected

說明:Promise的狀態改變只有兩種,且一個Promise對象只能改變一次,無論失敗還是成功都會得到一個結果輸出,成功的結果一般是value,失敗的結果一般是reason。

無論狀態是成功還是失敗,返回的都是promise。

Promise的值

實例對象中的另一個屬性 [PromiseResult]保存著異步任務 [成功/失敗] 的結果resolve/reject。

Promise的api

手寫Promide中的api:

(1)promise構造函數 Promise(executor){}

  • executor:執行器(resolve,reject)=>{}
  • resolve:內部定義成功時我們需要調用的函數value=>{}
  • reject:內部定義失敗時我們調用的函數 reason=>{}說明:executor會在Promise內部立即同步調用,異步操作在執行器中執行

(2)Promise.prototype.then方法:(onResolved,rejected)=>{}

  • onResolved函數:成功的回調函數value=>{}
  • rejected函數:失敗的回調函數reason=>{}

說明:指定用于得到成功value的成功回調和用于得到失敗reason的失敗回調,返回一個新的promise對象

(3)Promise.prototype.catch方法:(onRejected)=>{}

前三條是本文章中將要實現的手寫代碼,當然Promise還有其它的api接口。

(1)Promise.prototype.finally()方法

finally()方法用于指定不管 Promise 對象最后狀態如何,都會執行的操作。不管promise最后的狀態,在執行完then或catch指定的回調函數以后,都會執行finally方法指定的回調函數。

  1. promise 
  2. .then(result => {···}) 
  3. .catch(error => {···}) 
  4. .finally(() => {···}); 

(2)Promise.all()方法

Promise.all()方法用于將多個 Promise 實例,包裝成一個新的 Promise 實例。

  1. const p = Promise.all([p1, p2, p3]); 

p的狀態由p1、p2、p3決定,分成兩種情況。

  • 只有p1、p2、p3的狀態都變成fulfilled,p的狀態才會變成fulfilled,此時p1、p2、p3的返回值組成一個數組,傳遞給p的回調函數。
  • 只要p1、p2、p3之中有一個被rejected,p的狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調函數。

(3)Promise.race()方法

Promise.race()方法同樣是將多個 Promise 實例,包裝成一個新的 Promise 實例。

  1. const p = Promise.race([p1, p2, p3]); 

只要p1、p2、p3之中有一個實例率先改變狀態,p的狀態就跟著改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調函數。

(4)Promise.allSettled()方法

Promise.allSettled()方法接受一組 Promise 實例作為參數,包裝成一個新的 Promise 實例。只有等到所有這些參數實例都返回結果,不管是fulfilled還是rejected,包裝實例才會結束。

  1. const promises = [ 
  2.   fetch('/api-1'), 
  3.   fetch('/api-2'), 
  4.   fetch('/api-3'), 
  5. ]; 
  6.  
  7. await Promise.allSettled(promises); 
  8. removeLoadingIndicator(); 

該方法返回的新的 Promise 實例,一旦結束,狀態總是fulfilled,不會變成rejected。狀態變成fulfilled后,Promise 的監聽函數接收到的參數是一個數組,每個成員對應一個傳入Promise.allSettled()的 Promise 實例。

(5)Promise.any()方法

ES2021 引入了Promise.any()方法。該方法接受一組 Promise 實例作為參數,包裝成一個新的 Promise 實例返回。只要參數實例有一個變成fulfilled狀態,包裝實例就會變成fulfilled狀態;如果所有參數實例都變成rejected狀態,包裝實例就會變成rejected狀態。

(6)Promise.reject(reason)方法

Promise.reject(reason)方法也會返回一個新的 Promise 實例,該實例的狀態為rejected。

  1. const p = Promise.reject('出錯了'); 
  2. // 等同于 
  3. const p = new Promise((resolve, reject) => reject('出錯了')) 
  4.  
  5. p.then(nullfunction (s) { 
  6.   console.log(s) 
  7. }); 
  8. // 出錯了 

(7)Promise.resolve()方法 有時需要將現有對象轉為 Promise 對象,Promise.resolve()方法就起到這個作用。

  1. Promise.resolve('foo'
  2. // 等價于 
  3. new Promise(resolve => resolve('foo')) 

改變promsie狀態和指定回調函數誰先誰后?

(1)都有可能,正常情況下是先指定回調函數再改變狀態,但也可以先改變狀態再指定回調函數。

(2)如何改變狀態再指定回調?

  • 在執行器中直接調用resolve/reject
  • 延遲更長時間才進行調用then

(3)什么時候才能得到數據?

  • 如果先指定的回調,那當狀態發生改變,回調函數就會調用,得到數據
  • 如果先改變的狀態,那當指定回調時,回調函數就會進行調用,得到數據

示例:

  1. let p = new Promise((resolve,reject)=>{ 
  2.     resolve("成功了"); 
  3.     reject("失敗了"); 
  4. }); 
  5.  
  6. p.then((value)=>{ 
  7.     console.log(value); 
  8. },(reason)=>{ 
  9.     console.log(reason); 
  10. }) 

Promise規范

  1. "Promise"是一個具有then方法的對象或函數,其行為符合此規范。也就是說Promise是一個對象或函數
  2. "thenable"是一個具有then方法的對象或函數,也就是這個對象必須擁有then方法
  3. "value"是任何合法的js值(包括undefined或promise)
  4. promise中的異常需要使用throw語句進行拋出
  5. promise失敗的時候需要給出失敗的原因

then方法說明

  1. 一個promise必須要有一個then方法,而且可以訪問promise最終的結果,成功或者失敗的值
  2. then方法需要接收兩個參數,onfulfilled和onrejected這兩個參數是可選參數
  3. promise無論then方法是否執行完畢,只要promise狀態變了,then中綁定的函數就會執行。

鏈式調用

Promise最大的優點就是可以進行鏈式調用,如果一個then方法返回一個普通值,這個值就會傳遞給下一次的then中,作為成功的結果。

如果返回的是一個promise,則會把promise的執行結果傳遞下去取決于這個promise的成功或失敗。

如果返回的是一個報錯,就會執行到下一個then的失敗函數中。

三、手寫Promise代碼

面試經常考的手寫Promise代碼,可以仔細理解一下。

  1. // 手寫Promise 
  2. // 首先定義一個構造函數,在創建Promise對象的時候會傳遞一個函數executor, 
  3. // 這個函數會立即被調用,所以我們在Promise內部立即執行這個函數。 
  4. function Promise(executor){ 
  5.     // 用于保存promise的狀態 
  6.     this.status = "pending"
  7.     this.value;//初始值 
  8.     this.reason;//初始原因 
  9.     this.onResolvedCallbacks = [];//存放所有成功的回調函數 
  10.     this.onRejectedCallbacks = [];//存放所有失敗的回調函數 
  11.     //定義resolve函數 
  12.     const resolve = (value)=>{ 
  13.         if(this.status === "pending"){ 
  14.             this.status = "resolved"
  15.             this.value = value; 
  16.             this.onResolvedCallbacks.forEach(function(fn){ 
  17.                 fn() 
  18.             }) 
  19.         } 
  20.     } 
  21.     //定義reject函數 
  22.     const reject = (reason)=>{ 
  23.         if(this.status === "pending"){ 
  24.             this.status = "rejected"
  25.             this.reason = reason; 
  26.             this.onRejectedCallbacks.forEach(function(fn){ 
  27.                 fn() 
  28.             }) 
  29.         } 
  30.     } 
  31.     executor(resolve,reject); 
  32.  
  33. Promise.prototype.then = function(onFulfilled,onRejected){ 
  34. /* 
  35. 每次then都會返回一個新的promise 
  36.  
  37. 我們需要拿到當前then方法執行成功或失敗的結果, 
  38. 前一個then方法的返回值會傳遞給下一個then方法, 
  39. 所以這里我們要關心onFulfilled(self.value) 
  40. 和 onRejected(self.reason)的返回值,我們這里定義一個x來接收一下。 
  41.  
  42. 如果失敗拋錯需要執行reject方法,這里使用try...catch捕獲一下錯誤。 
  43. 也就是判斷then函數的執行結果和返回的promise的關系。 
  44. */ 
  45.     return new Promise((resolve,reject)=>{ 
  46.         //當Promise狀態為resolved時 
  47.         if(this.status === "resolved"){ 
  48.             try{ 
  49.                 resolve(onFulfilled(this.value)) 
  50.             }catch(error){ 
  51.                 reject(error) 
  52.             } 
  53.         } 
  54.         //當Promise狀態為rejected時 
  55.         if(this.status === "rejected"){ 
  56.             try { 
  57.                 resolve(onRejected(this.reason)) 
  58.             } catch (error) { 
  59.                 reject(error) 
  60.             } 
  61.         } 
  62.         //當Promise狀態為pendding 
  63.         if(this.status === "pending"){ 
  64.             this.onResolvedCallbacks.push(function(){ 
  65.                 try{ 
  66.                     resolve(onFulfilled(this.value)) 
  67.                 }catch(error){ 
  68.                     reject(error) 
  69.                 } 
  70.             }); 
  71.             this.onRejectedCallbacks.push(function(){ 
  72.                 try { 
  73.                     resolve(onRejected(this.reason)) 
  74.                 } catch (error) { 
  75.                     reject(error) 
  76.                 } 
  77.             }); 
  78.         } 
  79.     }) 

升級版Promise:

  1. class Promise{ 
  2.     /*首先定義一個構造函數,在創建Promise對象的時候會傳遞一個函數executor, 
  3.     這個函數會立即被調用,所以我們在Promise內部立即執行這個函數。*/ 
  4.     constructor(executor){ 
  5.         this.executor = executor(this.resolve,this.reject); 
  6.         
  7.  
  8.         this.onResolvedCallbacks = [];//存放所有成功的回調函數 
  9.         this.onRejectedCallbakcs = [];//存放所有失敗的回調函數 
  10.     } 
  11.      
  12.      // 用于存儲相應的狀態 
  13.     status = "pending"
  14.     // 初始值 
  15.     value; 
  16.     // 初始原因 
  17.     reason; 
  18.      
  19.     // executor在執行的時候會傳入兩個方法,一個是resolve, 
  20.     // 一個reject,所以我們要創建這兩個函數,而且需要把這兩個函數傳遞給executor。 
  21.     // 當我們成功或者失敗的時候,執行onFulfilled和onRejected的函數, 
  22.     // 也就是在resolve函數中和reject函數中分別循環執行對應的數組中的函數。 
  23.     // 定義成功事件 
  24.     resolve(value){ 
  25.         if(status === "pending"){ 
  26.             status = "resolved"
  27.             value = value; 
  28.             this.onResolvedCallbacks.forEach(fn=>{fn()}) 
  29.         } 
  30.     } 
  31.     // 定義失敗事件 
  32.     reject(){ 
  33.         if(this.status === "pending"){ 
  34.             this.status = "rejected"
  35.             this.reason = reason; 
  36.             this.onRejectedCallbakcs.forEach(fn=>{fn()}); 
  37.         } 
  38.     } 
  39.     // 這個時候當我們異步執行resolve方法時候,then中綁定的函數就會執行,并且綁定多個then的時候,多個方法都會執行。 
  40.  
  41.  
  42.     // Promise的對象存在一個then方法,這個then方法里面會有兩個參數,一個是成功的回調onFulfilled, 
  43.     // 另一個是失敗的回調onRejected,只要我們調用了resolve就會執行onFulfilled,調用了reject就會執行onRejected。 
  44.     // 為了保證this不錯亂,我們定義一個self存儲this。當我們調用了resolve或reject的時候,需要讓狀態發生改變. 
  45.     // 需要注意的是Promise的狀態只可改變一次,所以我們要判斷,只有當狀態未發生改變時,才去改變狀態。 
  46.     then(onFulfilled,onRejected){ 
  47.         // 判斷當前狀態進行回調 
  48.         if(this.status === "resolved"){ 
  49.             onFulfilled(self.value) 
  50.         }; 
  51.         if(this.status === "rejected"){ 
  52.             onRejected(self.reason) 
  53.         } 
  54.         // 當狀態還處于pending狀態時 
  55.         // 因為onFulfilled和onRejected在執行的時候需要傳入對應的value值,所我們這里用一個函數包裹起來,將對應的值也傳入進去。 
  56.         if(this.status === "pending"){ 
  57.             this.onResolvedCallbacks.push(()=>{onFulfilled(this.value)}); 
  58.             this.onResolvedCallbacks.push(()=>{onRejected(this.reason)}); 
  59.         } 
  60.     } 
  61.  

使用自己手寫的Promise源碼:

  1. let p = new Promise((resolve,reject)=>{ 
  2.     setTimeout(()=>{ 
  3.         resolve("成功了"
  4.     },1000) 
  5. }); 
  6.  
  7. p.then(function(value){ 
  8.     return 123; 
  9. }).then(value=>{ 
  10.     console.log("收到了成功的消息:",value); 
  11. }).catch(error=>{ 
  12.     console.log(error); 
  13. }); 
  14.  
  15. p.then(value=>{ 
  16.     console.log(value); 
  17. }) 

四、Async/Await

async用來表示函數是異步的,定義的async函數返回值是一個promise對象,可以使用then方法添加回調函數。

await 可以理解為是 async wait 的簡寫。await 必須出現在 async 函數內部,不能單獨使用。函數中只要使用await,則當前函數必須使用async修飾。

所以回調函數的終結者就是async/await。

async命令

  • async函數返回的是一個promise對象。
  • async函數內部return語句返回的值,會成為then方法回調的參數。
  • async函數內部拋出錯誤,會導致返回的 Promise 對象變為reject狀態。
  • 拋出的錯誤對象會被catch方法回調函數接收到。

async函數返回的 Promise 對象,必須等到內部所有await命令后面的 Promise 對象執行完,才會發生狀態改變,除非遇到return語句或者拋出錯誤。

也就是說,只有async函數內部的異步操作執行完,才會執行then方法指定的回調函數。

  1. async function fun(){ 
  2.     // return "hello wenbo"
  3.     throw new Error("ERROR"); 
  4. fun().then(v => console.log(v),reason=>console.log(reason));//Error: ERROR``` 

await命令

正常情況下,await命令后面是一個 Promise 對象,返回該對象的結果。如果不是 Promise 對象,就直接返回對應的值。

  1. async function fun(){ 
  2.     return await "zhaoshun"
  3.     // 等價于 return "zhaoshun"
  4. fun().then(value=>console.log(value));//zhaoshun 

另一種情況是,await命令后面是一個thenable對象(即定義了then方法的對象),那么await會將其等同于 Promise 對象。

  1. class Sleep{ 
  2.     constructor(timeout){ 
  3.         this.timeout = timeout; 
  4.     } 
  5.     then(resolve,reject){ 
  6.         const startTime = Date.now(); 
  7.         setTimeout(()=>resolve(Date.now() - startTime),this.timeout); 
  8.          
  9.  
  10.     } 
  11.  
  12.  
  13.     async ()=>{ 
  14.         const sleepTime = await new Sleep(1000); 
  15.         console.log(sleepTime);//1012 
  16.     } 
  17. )() 
  18.  
  19.  
  20. // js里面沒有休眠的語法,但是借助await命令可以讓程序停頓的時間 
  21. const sleepFun = (interval) => { 
  22.     return new Promise(resolve=>{ 
  23.         setTimeout(resolve,interval); 
  24.     }) 
  25.  
  26. // 用法 
  27. const asyncFun = async ()=>{ 
  28.     for(let i = 1; i <= 5; i++){ 
  29.         console.log(i); 
  30.         await sleepFun(1000); 
  31.     } 
  32. asyncFun(); 

從上面可以看到,await命令后面是一個Sleep對象的實例。這個實例不是 Promise 對象,但是因為定義了then方法,await會將其視為Promise處理。

await命令后面的 Promise 對象如果變為reject狀態,則reject的參數會被catch方法的回調函數接收到。

注意:上面代碼中,await語句前面沒有return,但是reject方法的參數依然傳入了catch方法的回調函數。這里如果在await前面加上return,效果是一樣的。

  • 任何一個await語句后面的 Promise 對象變為reject狀態,那么整個async函數都會中斷執行。
  • 使用try/catch可以很好處理前面await中斷,而后面不執行的情況。

示例:

  1. const fun = async ()=>{ 
  2.     try { 
  3.         await Promise.reject("ERROR"); 
  4.     } catch (error) { 
  5.          
  6.  
  7.     } 
  8.     return await Promise.resolve("success"); 
  9.  
  10. fun().then
  11.     value=>console.log(value),reason=>console.log(reason,"error")// 
  12. ).catch( 
  13.     error=>console.log(error)//ERROR 
  14. ); 

另一種方法是await后面的 Promise 對象再跟一個catch方法,處理前面可能出現的錯誤。

  1. const fun = async ()=>{ 
  2.     await Promise.reject("error").catch(e=>console.log(e)); 
  3.     return await Promise.resolve("success"); 
  4. fun().then(v=>console.log(v));//success 

錯誤處理

第一點:如果await后面的異步操作出錯,那么等同于async函數后面的promise對象被reject。

  1. const fun = async()=>{ 
  2.     await new Promise((resolve,reject)=>{ 
  3.         throw new Error("error"
  4.     }) 
  5. fun().then(v=>console.log(v)).catch(e=>console.log(e)); 

第二點:多個await命令后面的異步操作,如果不存在繼發關系,最好讓他們同時進行觸發。

  1. const [fun1,fun2] = await Promise.all([getFun(),getFoo()]); 
  2.  
  3. const fooPromise = getFoo(); 
  4. const funPromise = getFun(); 
  5. const fun1 = await fooPromise(); 
  6. const fun2 = await funPromise(); 

第三點:await命令只能用在async函數之中,如果用在普通函數,就會報錯。

  1. async function dbFuc(db) { 
  2.   let docs = [{}, {}, {}]; 
  3.  
  4.   // 報錯 
  5.   docs.forEach(function (doc) { 
  6.     await db.post(doc); 
  7.   }); 

第四點:async 函數可以保留運行堆棧。

小結在這篇文章中我們總結了異步編程和回調函數的解決方案Promise,以及回調終結者aysnc/await。

  • Promise有三個狀態:pending、rejected、resolved。
  • Promise的狀態改變,只能改變一次,只有兩種改變:pending變為resolved/fullfilled、pending變為rejected。
  • Promise最大優點就是可以進行鏈式調用。
  • async用來表示函數是異步的,定義的async函數返回值是一個promise對象。
  • 函數中只要使用await,則當前函數必須使用async修飾。
  • 回調函數的終結者就是async/await。

參考文章

  • 《異步終結者 async await,了解一下》
  • 《一次性讓你懂async/await,解決回調地獄》
  • 《面試精選之Promise》
  • 《BAT前端經典面試問題:史上最最最詳細的手寫Promise教程》
  • 《Promise實現原理(附源碼)》
  • 《JavaScript高級程序設計(第四版)》
  • 《你不知道的JavaScript(中卷)》
  • 阮一峰《ES6 入門教程》

本文轉載自微信公眾號「前端萬有引力」,可以通過以下二維碼關注。轉載本文請聯系前端萬有引力公眾號。

 

責任編輯:姜華 來源: 前端萬有引力
相關推薦

2023-10-08 10:21:11

JavaScriptAsync

2021-06-07 09:44:10

JavaScript開發代碼

2017-04-10 15:57:10

AsyncAwaitPromise

2024-09-02 14:12:56

2023-03-29 10:19:44

異步編程AsyncPromise

2017-06-19 09:12:08

JavaScriptPromiseAsync

2022-11-21 09:01:00

Swift并發結構

2021-06-09 07:01:30

前端CallApply

2014-07-15 10:08:42

異步編程In .NET

2014-07-15 10:31:07

asyncawait

2021-07-15 14:29:06

LRU算法

2016-11-22 11:08:34

asyncjavascript

2021-09-06 08:13:35

APM系統監控

2024-02-01 09:39:02

asyncawaitPromise

2024-03-05 18:15:28

AsyncAwait前端

2022-06-24 08:33:13

ECMAScriptjavaScript

2012-07-22 15:59:42

Silverlight

2021-07-20 10:26:12

JavaScriptasyncawait

2022-08-27 13:49:36

ES7promiseresolve

2024-12-30 08:22:35

點贊
收藏

51CTO技術棧公眾號

久久久久久久久影院| 男女性杂交内射妇女bbwxz| 在线免费黄色| 国产mv日韩mv欧美| 欧美与欧洲交xxxx免费观看| 99精品全国免费观看| 色综合视频一区二区三区44| 亚洲va国产va欧美va观看| 青青草国产精品| av无码精品一区二区三区宅噜噜| 在线视频亚洲| 久久色在线播放| 国产黄色三级网站| 伊人久久一区| 色婷婷久久综合| 欧美日韩午夜爽爽| 国产高清在线| 成人v精品蜜桃久久一区| 国产精品678| 亚欧洲精品在线视频| 欧美hd在线| 亚洲精品中文字| 亚洲熟妇一区二区| 国产三级一区| 日本久久一区二区| 青青青青在线视频| 美女羞羞视频在线观看| 久久只精品国产| 在线视频欧美精品| 欧美成人精品一区二区| 黄色a一级视频| 日韩在线亚洲| 欧美日本视频在线| 日本女优爱爱视频| 国产不卡人人| 亚洲永久精品国产| 在线观看日本一区| 成年人在线视频| 久久亚洲一级片| 蜜桃免费一区二区三区| 人成网站在线观看| 国产精品自拍网站| 成人免费观看a| 狠狠狠狠狠狠狠| 亚欧成人精品| 欧洲中文字幕国产精品| 日本中文字幕免费| 国内揄拍国内精品久久| 久久成年人视频| 91杏吧porn蝌蚪| 久久午夜精品视频| 日韩精品一页| 欧美精品一二三四| 一区二区三区 日韩| 久久天堂av| 欧美性高清videossexo| 色七七在线观看| av成人在线观看| 欧美猛男男办公室激情| 天天色天天综合网| 精品入口麻豆88视频| 7777精品伊人久久久大香线蕉经典版下载 | 免费看av成人| 日韩精品视频免费在线观看| 黄色免费视频网站| 日韩精品福利一区二区三区| 日韩高清免费观看| 西西444www无码大胆| 精品国产网站| 菠萝蜜影院一区二区免费| 日本欧美一区二区三区不卡视频| 神马电影久久| 色婷婷综合成人av| 少妇人妻丰满做爰xxx| 国产一区日韩欧美| 97视频在线观看免费| 69亚洲精品久久久蜜桃小说| 天堂av在线一区| 国产精品一区二区久久精品| 国产欧美综合视频| 波多野结衣91| 欧美日韩一区在线观看视频| av播放在线| 亚洲尤物在线视频观看| 少妇av一区二区三区无码| 欧洲av不卡| 欧美军同video69gay| 日本中文字幕精品| 亚洲最好看的视频| 成人欧美一区二区三区1314| 日韩在线高清视频| 亚洲二区在线播放| 亚洲伦伦在线| 国产精品一区二区久久久久| 精品人妻一区二区三区含羞草| 99久久综合色| 一区视频二区视频| a国产在线视频| 欧美日韩免费观看一区二区三区| 久久久男人的天堂| 波多野结衣在线观看一区二区| 欧美老妇交乱视频| 丰满少妇xoxoxo视频| 理论片日本一区| 久久精彩视频| 成人免费高清| 在线视频国产一区| 一边摸一边做爽的视频17国产| 精品久久91| 国内精久久久久久久久久人| 男人天堂网站在线| 成人国产免费电影| 色婷婷久久综合| 午夜福利三级理论电影| 成人在线免费观看91| 国内久久久精品| 国产免费一区二区三区免费视频| 久久久久高清精品| 免费人成自慰网站| 在线观看亚洲精品福利片| 亚洲毛片在线看| 久久精品国产亚洲AV无码麻豆 | 国内外成人免费在线视频| 国产厕拍一区| 美日韩精品视频免费看| 中文字幕第2页| 久久一区二区三区国产精品| 国产 欧美 日韩 一区| 欧美a一级片| 亚洲免费视频观看| 久久久国产高清| 国产成人综合亚洲91猫咪| 在线视频福利一区| 欧美xnxx| 一色桃子一区二区| 精品人妻无码一区二区性色 | 国产精品密蕾丝袜| 国产亚洲成人一区| 国产一区玩具在线观看| 成人77777| 91传媒视频在线播放| 一级片手机在线观看| 亚洲深夜激情| 精品久久久久久中文字幕动漫 | 114国产精品久久免费观看| 三区四区电影在线观看| 欧美日韩一区视频| 长河落日免费高清观看| 免费精品视频在线| 亚洲欧洲日韩综合二区| 福利视频亚洲| 久久色免费在线视频| 国产99999| 亚洲成a人在线观看| www.17c.com喷水少妇| 亚洲精品四区| 久久久久久国产精品mv| 韩国美女久久| 中文字幕亚洲欧美一区二区三区| 国产三级理论片| 亚洲欧洲日产国码二区| 91人妻一区二区三区| 欧美日韩91| 精品久久久久亚洲| 精品3atv在线视频| 社区色欧美激情 | 国产三级三级在线观看| 亚洲永久精品国产| wwwwxxxx国产| 捆绑紧缚一区二区三区视频| 精品嫩模一区二区三区| 国产一区在线电影| 国产97在线播放| 免费在线观看av网站| 日韩精品一区二区三区在线播放| 日韩少妇裸体做爰视频| 久久精品亚洲国产奇米99| www.久久91| 亚洲视频综合| 性欧美大战久久久久久久免费观看 | 88av在线播放| 日本免费新一区视频| 国产精品夜夜夜爽张柏芝| 国产96在线亚洲| 国产精品手机播放| gogo高清在线播放免费| 精品一区二区三区三区| 亚洲自拍第二页| 亚洲国产成人精品视频| 成人在线一级片| 成人小视频在线| 黄色成人免费看| 亚洲国产一区二区三区a毛片| 欧美日韩精品免费看| 精品91福利视频| 日本久久久久亚洲中字幕| 国产激情在线视频| 亚洲欧美日韩第一区| japanese国产| 在线观看成人免费视频| 亚洲一区二区91| 国产精品久久久久久久第一福利| 亚洲av无码一区东京热久久| 蜜臀av一区二区三区| a天堂资源在线观看| 日韩欧美一区二区三区在线视频 | 性欧美成人播放77777| 国产一区二区三区美女| 日韩一级片播放| 怡红院精品视频在线观看极品| 亚欧洲精品在线视频免费观看| 猫咪成人在线观看| 51国产成人精品午夜福中文下载 | 欧美日韩亚州综合| 中文字幕亚洲高清| 亚洲精品你懂的| 性少妇bbw张开| 成人av资源站| 杨幂一区二区国产精品| 蜜桃av一区二区三区电影| 久久国产成人精品国产成人亚洲| 永久91嫩草亚洲精品人人| 亚洲国产欧美日韩| 久久av免费看| 免费精品视频一区| 欧洲精品一区| 好吊色欧美一区二区三区视频| 日韩三级精品| 91在线免费网站| 青娱乐极品盛宴一区二区| 国产97在线观看| 深夜成人影院| 国产成人精品免高潮费视频| 蜜桃视频www网站在线观看| 欧美激情欧美狂野欧美精品| 在线观看三级视频| 不卡毛片在线看| 国产一二三区在线观看| 久久久极品av| 黄色网址免费在线观看| 日韩中文字幕视频| 免费看美女视频在线网站| 色一区av在线| 欧美jizzhd欧美| 日韩视频免费看| 成人在线影视| 欧美剧在线观看| 97人澡人人添人人爽欧美| 欧美精品电影免费在线观看| caoporn视频在线| 69精品小视频| 极品美女一区| 国产精品久久不能| 久久久久毛片| 亚洲一区美女视频在线观看免费| 日韩三级不卡| 精品日本一区二区三区在线观看 | bt欧美亚洲午夜电影天堂| 极品白嫩的小少妇| av在线不卡观看免费观看| 欧美熟妇精品黑人巨大一二三区| 2017欧美狠狠色| 青青青视频在线播放| 亚洲天堂中文字幕| 久久久久成人精品无码| 亚洲国产精品久久人人爱| 中文在线第一页| 欧美日韩专区在线| 精品国产av 无码一区二区三区| 日韩一级大片在线| 性xxxx18| 日韩视频在线观看免费| 国产亚av手机在线观看| 欧美一级电影久久| 成人四虎影院| 国产经典一区二区三区| 亚洲精品播放| 国产四区在线观看| 一区二区三区四区五区精品视频 | 99国产精品白浆在线观看免费| 亚洲一区日韩在线| 三上悠亚av一区二区三区| 国产精品夜夜嗨| 波多野结衣 在线| 综合亚洲深深色噜噜狠狠网站| 亚洲精品在线观看av| 欧美在线播放高清精品| 亚洲va欧美va| 一区二区三区四区在线观看视频| 97影院秋霞午夜在线观看| 欧美一级片久久久久久久| 成人在线日韩| 欧美一区二区三区四区在线观看地址 | 中文字幕在线视频免费| 欧美刺激脚交jootjob| 韩日在线视频| 韩剧1988在线观看免费完整版| 四虎4545www精品视频| 官网99热精品| 色婷婷综合网| 国产视频九色蝌蚪| 精品在线免费观看| 五级黄高潮片90分钟视频| 亚洲啪啪综合av一区二区三区| 欧产日产国产69| 精品国产91洋老外米糕| aiai在线| 日韩av色综合| 欧美人妖视频| 欧美乱做爰xxxⅹ久久久| 久久福利资源站| 亚洲自拍偷拍图| 精品久久久久久久久久ntr影视| 国产又大又黑又粗| 国产亚洲精品91在线| 成人免费图片免费观看| www.久久久| 亚洲精品国产成人影院| 黄色三级视频片| 91色porny蝌蚪| 国产一卡二卡在线| 日韩色视频在线观看| 蜜桃视频在线观看免费视频网站www| 国产精国产精品| 亚洲精品中文字幕99999| 日韩小视频在线播放| 国产91精品在线观看| 一区二区国产精品精华液| 欧美日韩精品是欧美日韩精品| 男女视频在线观看免费| 97成人在线视频| 久久99精品国产自在现线| 黄色一级片黄色| 国产91对白在线观看九色| 69xx绿帽三人行| 日韩欧美一卡二卡| 91香蕉在线观看| 91日本视频在线| 久久久人成影片免费观看| 青青草久久伊人| 亚洲男人天堂av网| 国产欧美日韩成人| 欧美激情一区二区三区高清视频| 一本一道久久a久久| 成年人视频网站免费| 国产91精品露脸国语对白| 久草视频在线免费看| 欧美不卡一区二区三区| bl视频在线免费观看| 动漫精品视频| 亚洲视频www| 精品人妻互换一区二区三区| 在线观看一区二区视频| 成年人视频在线免费观看| 成人国产精品久久久| 这里只有精品在线| 国模大尺度视频| 亚洲电影在线播放| 少妇精品视频一区二区 | 欧美jizz18| japanese在线播放| 成人晚上爱看视频| 黄色在线观看国产| 在线观看日韩视频| 久久一级大片| 日韩网站在线免费观看| 91婷婷韩国欧美一区二区| 久久这里只有精品9| 久久精品一区中文字幕| 7777精品| 日本爱爱免费视频| 亚洲在线视频一区| 欧美日韩国产中文字幕在线| 国产欧美日韩高清| 你懂的视频一区二区| 亚洲精品视频大全| 欧美日韩国产bt| 成人免费图片免费观看| 亚洲精品一区二区三| 国产精品1区2区3区| 亚洲精品男人的天堂| 久久亚洲综合国产精品99麻豆精品福利 | 777777国产7777777| 亚洲高清福利视频| 欧美aaaaaa| 男人靠女人免费视频网站| 中文字幕亚洲欧美在线不卡| 国内爆初菊对白视频| 国产精品成人va在线观看| 国产综合网站| 波多野结衣家庭教师在线观看 | 国产色a在线| 亚洲一区二区中文| 三级亚洲高清视频| 欧美成欧美va| 亚洲性av网站| 狼人天天伊人久久| 午夜激情视频网| 在线亚洲一区观看| 国产精品蜜芽在线观看|