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

面試官不要再問我 axios 了?我能手寫簡易版的 axios

開發 前端
作為我們工作中的常用的ajax請求庫,作為前端工程師的我們當然是想一探究竟,axios究竟是如何去架構整個框架,中間的攔截器、適配器、 取消請求這些都是我們經常使用的。

 [[436491]]

作為我們工作中的常用的ajax請求庫,作為前端工程師的我們當然是想一探究竟,axios究竟是如何去架構整個框架,中間的攔截器、適配器、 取消請求這些都是我們經常使用的。

前言

由于axios源碼中有很多不是很重要的方法,而且很多方法為了考慮兼容性,并沒有考慮到用es6 的語法去寫。本篇主要是帶你去梳理axios的主要流程,并用es6重寫簡易版axios

  •  攔截器
  •  適配器
  •  取消請求

攔截器

一個axios實例上有兩個攔截器,一個是請求攔截器, 然后響應攔截器。我們下看下官網的用法:添加攔截器 

  1. // 添加請求攔截器  
  2. axios.interceptors.request.use(function (config) {  
  3.     // 在發送請求之前做些什么  
  4.     return config;  
  5.   }, function (error) {  
  6.     // 對請求錯誤做些什么  
  7.     return Promise.reject(error);  
  8.   }); 

移除攔截器 

  1. const myInterceptor = axios.interceptors.request.use(function () {/*...*/});  
  2. axios.interceptors.request.eject(myInterceptor); 

其實源碼中就是,所有攔截器的執行 所以說肯定有一個forEach方法。

思路理清楚了,現在我們就開始去寫吧。代碼我就直接發出來,然后我在下面注解。 

  1. export class InterceptorManager {  
  2.   constructor() {  
  3.     // 存放所有攔截器的棧  
  4.     this.handlers = []  
  5.   }  
  6.   use(fulfilled, rejected) {  
  7.     this.handlers.push({  
  8.       fulfilled,  
  9.       rejected,  
  10.     })  
  11.     //返回id 便于取消  
  12.     return this.handlers.length - 1  
  13.   } 
  14.   // 取消一個攔截器  
  15.   eject(id) {  
  16.     if (this.handlers[id]) {  
  17.       this.handlers[id] = null  
  18.     }  
  19.   }  
  20.   // 執行棧中所有的hanlder  
  21.   forEach(fn) {  
  22.     this.handlers.forEach((item) => {  
  23.       // 這里為了過濾已經被取消的攔截器,因為已經取消的攔截器被置null  
  24.       if (item) {  
  25.         fn(item)  
  26.       }  
  27.     })  
  28.   }  

攔截器這個類我們已經初步實現了,現在我們去實現axios 這個類,還是先看下官方文檔,先看用法,再去分析。

axios(config) 

  1. // 發送 POST 請求  
  2. axios({  
  3.   method: 'post',  
  4.   url: '/user/12345',  
  5.   data: {  
  6.     firstName: 'Fred',  
  7.     lastName: 'Flintstone'  
  8.   }  
  9. }); 

axios(url[, config]) 

  1. // 發送 GET 請求(默認的方法)  
  2. axios('/user/12345'); 

Axios 這個類最核心的方法其實還是 request 這個方法。我們先看下實現吧!

  1. class Axios {  
  2.   constructor(config) {  
  3.     this.defaults = config  
  4.     this.interceptors = {  
  5.       request: new InterceptorManager(),  
  6.       response: new InterceptorManager(),  
  7.     }  
  8.   }  
  9.   // 發送一個請求  
  10.   request(config) {  
  11.     // 這里呢其實就是去處理了 axios(url[,config])  
  12.     if (typeof config == 'string') {  
  13.       config = arguments[1] || {}  
  14.       config.url = arguments[0]  
  15.     } else {  
  16.       configconfig = config || {}  
  17.     }  
  18.     // 默認get請求,并且都轉成小寫  
  19.     if (config.method) {  
  20.       configconfig.method = config.method.toLowerCase()  
  21.     } else {  
  22.       config.method = 'get'  
  23.     }  
  24.     // dispatchRequest 就是發送ajax請求  
  25.     const chain = [dispatchRequest, undefined]  
  26.     //  發生請求之前加入攔截的 fulfille 和reject 函數  
  27.     this.interceptors.request.forEach((item) => {  
  28.       chain.unshift(item.fulfilled, item.rejected)  
  29.     })  
  30.     // 在請求之后增加 fulfilled 和reject 函數  
  31.     this.interceptors.response.forEach((item) => {  
  32.       chain.push(item.fulfilled, item.rejected)  
  33.     })  
  34.     // 利用promise的鏈式調用,將參數一層一層傳下去  
  35.     let promise = Promise.resolve(config)  
  36.     //然后我去遍歷 chain  
  37.     while (chain.length) {  
  38.       // 這里不斷出棧 直到結束為止  
  39.       promisepromise = promise.then(chain.shift(), chain.shift())  
  40.     }  
  41.     return promise  
  42.   }  

這里其實就是體現了axios設計的巧妙, 維護一個棧結構 + promise 的鏈式調用 實現了 攔截器的功能, 可能有的小伙伴到這里還是不是很能理解,我還是給大家畫一個草圖去模擬下這個過程。

假設我有1個請求攔截器handler和1個響應攔截器handler

一開始我們棧中的數據就兩個

這個沒什么問題,由于有攔截器的存在,如果存在的話,那么我們就要往這個棧中加數據,請求攔截器顧名思義要在請求之前所以是unshift。加完請求攔截器我們的棧變成了這樣。

沒什么問題,然后請求結束后,我們又想對請求之后的數據做處理,所以響應攔截的數據自然是push了。這時候棧結構變成了這樣:

然后遍歷整個棧結構,每次出棧都是一對出棧, 因為promise 的then 就是 一個成功,一個失敗嘛。遍歷結束后,返回經過所有處理的promise,然后你就可以拿到最終的值了。

adapter

Adapter: 英文解釋是適配器的意思。這里我就不實現了,我帶大家看一下源碼。adapter 做了一件事非常簡單,就是根據不同的環境 使用不同的請求。如果用戶自定義了adapter,就用config.adapter。否則就是默認是default.adpter。

  1. var adapter = config.adapter || defaults.adapter;  
  2. return adapter(config).then() ...  

繼續往下看deafults.adapter做了什么事情: 

  1. function getDefaultAdapter() {  
  2.   var adapter;  
  3.   if (typeof XMLHttpRequest !== 'undefined') {  
  4.     // For browsers use XHR adapter  
  5.     adapter = require('./adapters/xhr');  
  6.   } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {  
  7.     // For node use HTTP adapter  
  8.     adapter = require('./adapters/http');  
  9.   }  
  10.   return adapter;  

其實就是做個選擇:如果是瀏覽器環境:就是用xhr 否則就是node 環境。判斷process是否存在。從寫代碼的角度來說,axios源碼的這里的設計可擴展性非常好。有點像設計模式中的適配器模式, 因為瀏覽器端和node 端 發送請求其實并不一樣, 但是我們不重要,我們不去管他的內部實現,用promise包一層做到對外統一。所以 我們用axios 自定義adapter 器的時候, 一定是返回一個promise。ok請求的方法我在下面模擬寫出。

cancleToken

我首先問大家一個問題,取消請求原生瀏覽器是怎么做到的?有一個abort 方法。可以取消請求。那么axios源碼肯定也是運用了這一點去取消請求。現在瀏覽器其實也支持fetch請求, fetch可以取消請求?很多同學說是不可以的,其實不是?fetch 結合 abortController 可以實現取消fetch請求。我們看下例子: 

  1. const controller = new AbortController();  
  2. const { signal } = controller;  
  3. fetch("http://localhost:8000", { signal }).then(response => {  
  4.     console.log(`Request 1 is complete!`);  
  5. }).catch(e => {  
  6.     console.warn(`Fetch 1 error: ${e.message}`);  
  7. });  
  8. // Wait 2 seconds to abort both requests  
  9. setTimeout(() => controller.abort(), 2000); 

但是這是個實驗性功能,可惡的ie。所以我們這次還是用原生的瀏覽器xhr基于promise簡單的封裝一下。代碼如下: 

  1. export function dispatchRequest(config) {  
  2.   return new Promise((resolve, reject) => {  
  3.     const xhr = new XMLHttpRequest()  
  4.     xhr.open(config.method, config.url)  
  5.     xhr.onreadystatechange = function () {  
  6.       if (xhr.status >= 200 && xhr.status <= 300 && xhr.readyState === 4) {  
  7.         resolve(xhr.responseText)  
  8.       } else {  
  9.         reject('失敗了')  
  10.       }  
  11.     }  
  12.     if (config.cancelToken) {  
  13.       // Handle cancellation  
  14.       config.cancelToken.promise.then(function onCanceled(cancel) {  
  15.         if (!xhr) {  
  16.           return 
  17.         }  
  18.         xhr.abort()  
  19.         reject(cancel)  
  20.         // Clean up request  
  21.         xhr = null  
  22.       }) 
  23.     }  
  24.     xhr.send()  
  25.   })  

Axios 源碼里面做了很多處理, 這里我只做了get處理,我主要的目的就是為了axios是如何取消請求的。先看下官方用法:

主要是兩種用法:

使用 cancel token 取消請求 

  1. const CancelToken = axios.CancelToken;  
  2. const source = CancelToken.source();  
  3. axios.get('/user/12345', {  
  4.   cancelToken: source.token  
  5. }).catch(function(thrown) {  
  6.   if (axios.isCancel(thrown)) {  
  7.     console.log('Request canceled', thrown.message);  
  8.   } else {  
  9.      // 處理錯誤  
  10.   }  
  11. });  
  12. axios.post('/user/12345', {  
  13.   name: 'new name'  
  14. }, {  
  15.   cancelToken: source.token  
  16. })  
  17. // 取消請求(message 參數是可選的)  
  18. source.cancel('Operation canceled by the user.'); 

還可以通過傳遞一個 executor 函數到 CancelToken 的構造函數來創建 cancel token: 

  1. const CancelToken = axios.CancelToken;  
  2. let cancel;  
  3. axios.get('/user/12345', {  
  4.   cancelToken: new CancelToken(function executor(c) {  
  5.     // executor 函數接收一個 cancel 函數作為參數  
  6.     ccancel = c;  
  7.   })  
  8. });  
  9. // cancel the request  
  10. cancel(); 

看了官方用法 和結合axios源碼,我給出以下實現: 

  1. export class cancelToken {  
  2.     constructor(exactor) {  
  3.         if (typeof executor !== 'function') {  
  4.         throw new TypeError('executor must be a function.')  
  5.         }  
  6.         // 這里其實將promise的控制權 交給 cancel 函數  
  7.         // 同時做了防止多次重復cancel 之前 Redux 還有React 源碼中也有類似的案列  
  8.         const resolvePromise;  
  9.         this.promise =  new Promise(resolve => {  
  10.             resolveresolvePromise = resolve;  
  11.         })  
  12.         this.reason = undefined      
  13.          const cancel  = (message) => {  
  14.             if(this.reason) {  
  15.                 return;  
  16.             }  
  17.             this.reason = 'cancel' + message;  
  18.             resolvePromise(this.reason);  
  19.         }  
  20.         exactor(cancel)  
  21.     }  
  22.     throwIfRequested() {  
  23.         if(this.reason) {  
  24.             throw this.reason  
  25.         }  
  26.     }   
  27.      // source 其實本質上是一個語法糖 里面做了封裝  
  28.     static source() {  
  29.         const cancel;  
  30.         const token = new cancelToken(function executor(c) {  
  31.             ccancel = c;  
  32.         });  
  33.         return {  
  34.             token: token,  
  35.             cancel: cancel  
  36.         };  
  37.     }  

截止到這里大體axios 大體功能已經給出。

接下來我就測試下我的手寫axios,有沒有什么問題? 

  1. <script type="module" >  
  2.    import Axios from './axios.js';  
  3.    const config = { url:'http://101.132.113.6:3030/api/mock' }  
  4.    const axios =  new Axios();  
  5.    axios.request(config).then(res => {  
  6.        console.log(res,'0000')  
  7.    }).catch(err => { 
  8.       console.log(err)  
  9.    })  
  10. /script> 

打開瀏覽器看一下結果:

成功了ok, 然后我來測試一下攔截器的功能,代碼更新成下面這樣: 

  1. import Axios from './axios.js';  
  2. const config = { url:'http://101.132.113.6:3030/api/mock' }  
  3. const axios =  new Axios();  
  4. // 在axios 實例上掛載屬性  
  5. const err = () => {}  
  6. axios.interceptors.request.use((config)=> {  
  7.     console.log('我是請求攔截器1')  
  8.     config.id = 1 
  9.     return  config  
  10. },err )  
  11. axios.interceptors.request.use((config)=> {  
  12.     config.id = 2  
  13.     console.log('我是請求攔截器2')  
  14.     return config  
  15. },err)  
  16. axios.interceptors.response.use((data)=> {  
  17.     console.log('我是響應攔截器1',data )  
  18.     data += 1;  
  19.     return data;  
  20. },err)  
  21. axios.interceptors.response.use((data)=> {  
  22.     console.log('我是響應攔截器2',data )  
  23.     return  data  
  24. },err)  
  25. axios.request(config).then(res => {  
  26.     // console.log(res,'0000')  
  27.     // return res;  
  28. }).catch(err => {  
  29.     console.log(err)  
  30. })  console.log(err)}) 

ajax 請求的結果 我是resolve(1) ,所以我們看下輸出路徑:

沒什么問題, 響應后的數據我加了1。

接下來我來是取消請求的兩種方式 :

  1. // 第一種方式  
  2. let  cancelFun = undefined 
  3. const cancelInstance = new cancelToken((c)=> 
  4.     ccancelFun = c;  
  5. });  
  6. config.cancelToken = cancelInstance 
  7. // 50 ms 就取消請求  
  8. setTimeout(()=> 
  9.     cancelFun('取消成功')  
  10. },50)  
  11. 第二種方式:  
  12. const { token, cancel }  = cancelToken.source();  
  13. config.cancelToken = token 
  14. setTimeout(()=> 
  15.     cancel()  
  16. },50) 

結果都是OK的,至此axios簡單源碼終于搞定了。

反思

本篇文章只是把axios源碼的大體流程走了一遍, axios源碼內部還是做了很多兼容比如:配置優先級:他有一個mergeConfig 方法, 還有數據轉換器。不過這些不影響我們對axios源碼的整體梳理, 源碼中其實有一個createInstance,至于為什么有?我覺得就是為了可擴展性更好, 將來有啥新功能,直接在原有axios的實例的原型鏈上去增加,代碼可維護性強, axios.all spread 都是實例new出來再去掛的,不過都很簡單,沒啥的。有興趣大家自行閱讀。 

 

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2020-10-20 09:12:57

axios核心原理

2020-04-16 08:22:11

HTTPS加解密協議

2021-12-02 08:19:06

MVCC面試數據庫

2019-07-10 10:06:24

面試官三次握手四次揮手

2022-03-14 10:14:43

底層系統Nacos

2022-04-10 18:10:24

CURD鏈表

2018-09-28 05:25:53

TopK算法代碼

2020-08-26 08:18:39

數據索引查詢

2020-12-01 11:50:49

數據庫Redis面試

2018-11-09 09:34:05

面試Spring Clou底層

2018-10-28 22:37:00

計數排序排序面試

2018-11-01 13:49:23

桶排序排序面試

2022-01-10 11:04:41

單鏈表面試編程

2020-12-03 07:39:50

HashMap底層數據

2021-08-10 18:36:02

Express原理面試

2020-11-24 07:48:32

React

2022-02-11 13:44:56

fiber架構React

2022-05-24 08:03:28

InnoDBMySQL數據

2021-05-08 07:53:33

面試線程池系統

2021-10-25 08:49:32

索引數據庫MySQL
點贊
收藏

51CTO技術棧公眾號

亚洲天堂中文字幕| 国产亚洲福利| 日韩一卡二卡三卡四卡| 免费观看国产视频在线| 亚洲av色香蕉一区二区三区| 一区二区日韩免费看| 这里只有精品在线播放| 男人操女人下面视频| 污污的视频在线观看| 92精品国产成人观看免费| 国产精品久久91| 超碰手机在线观看| 欧美性生活一级片| 欧美日韩国产综合视频在线观看| 国产91沈先生在线播放| 可以直接在线观看的av| 国产麻豆成人传媒免费观看| 97超级碰碰碰| 国产97免费视频| 亚洲第一福利专区| 欧美精品高清视频| 中国丰满人妻videoshd| 黄色免费网站在线| 久久―日本道色综合久久| 91亚洲国产成人精品性色| 日韩乱码在线观看| 91精品亚洲| 国产亚洲精品美女久久久| 任你躁av一区二区三区| 97精品国产99久久久久久免费| 亚洲精品ww久久久久久p站| 免费一区二区三区在在线视频| 999av视频| 日本亚洲免费观看| 欧美一级成年大片在线观看| 国产一二三区精品| 成人av动漫在线观看| 日韩电影网在线| 免费观看一区二区三区| 亚洲免费资源| 欧美中文字幕一区| 国产免费成人在线| 成av人片在线观看www| 亚洲精品国产精华液| 水蜜桃一区二区三区| 三区在线观看| 99re亚洲国产精品| 国产麻豆一区二区三区在线观看| 国产三级视频在线播放| 麻豆国产精品一区二区三区 | 91中文字幕在线观看| 国产日韩久久久| 午夜一级久久| 欧美在线激情网| av资源免费观看| 日韩午夜黄色| 午夜精品久久久久久久99热| 久久久91视频| 综合一区二区三区| 欧美成人久久久| 全网免费在线播放视频入口| 影视一区二区| 欧美精品中文字幕一区| 欧美成人黄色网| 国产精品videossex久久发布| 欧美日韩高清区| 精品少妇theporn| 在线看片日韩| 欧美专区在线播放| 自拍偷拍校园春色| 秋霞电影网一区二区| 国产欧美日韩最新| 国产免费的av| 成人综合婷婷国产精品久久蜜臀| 国产一区二区在线观看免费播放| 色网站免费观看| 久久久久久久一区| 亚洲免费在线精品一区| av香蕉成人| 亚洲成人黄色影院| 日本成人在线免费视频| 成人看片毛片免费播放器| 制服.丝袜.亚洲.中文.综合| 制服.丝袜.亚洲.中文.综合懂| 极品束缚调教一区二区网站| 亚洲精品小视频| 国产18无套直看片| 欧美成人tv| 欧美一级大片在线免费观看| 中文字幕免费在线看| 国产伦精品一区二区三区视频青涩| 北条麻妃高清一区| 你懂的视频在线| 亚洲欧洲av在线| 水蜜桃色314在线观看| 经典三级一区二区| 日韩精品在线网站| 日韩在线免费观看av| 91精品久久久久久久蜜月 | 男女免费视频网站| 亚洲综合国产激情另类一区| 成人国产精品一区| 天堂av中文在线资源库| 国产精品青草久久| 婷婷无套内射影院| 黄色欧美视频| 亚洲国产天堂久久综合网| 九一在线免费观看| 在线国产欧美| 91精品免费视频| 免费黄色片在线观看| 亚洲欧美二区三区| 国内自拍视频一区| 999久久久精品一区二区| 国产一区二区三区久久精品| 国产一级aa大片毛片| 麻豆成人久久精品二区三区红| 国产一区精品在线| free性欧美hd另类精品| 日本高清不卡视频| 亚洲美女在线播放| 中文不卡在线| 国产精品久久一区主播| 神马精品久久| 亚洲一区二区三区视频在线播放| 亚洲久久中文字幕| 国产精品嫩草影院在线看| 欧美日韩国产va另类| 一区二区三区黄| 国产欧美日韩卡一| 久久久久久久久久久福利| 77成人影视| 久久最新资源网| 亚洲天堂aaa| 国产欧美精品一区aⅴ影院| 无罩大乳的熟妇正在播放| 一区二区在线免费播放| 日韩最新在线视频| 中文字幕乱码视频| 国产日韩欧美激情| 99精品视频播放| 亚洲成aⅴ人片久久青草影院| 欧美精品久久久久久久久| 99国产精品久久久久99打野战| 国产精品久久久久影视| the porn av| 日韩黄色大片| 国产美女91呻吟求| av片在线免费观看| 欧美日韩你懂的| 又色又爽的视频| 蜜桃精品视频在线| 亚洲一区二区在线免费观看| 久久精品资源| 久久久精品网站| 国产欧美综合视频| 亚洲欧洲精品一区二区精品久久久| 一区二区三区 日韩| 成人高清电影网站| 国产自摸综合网| 国产高清一区二区三区视频| 日韩亚洲欧美一区二区三区| 神马久久精品综合| 国产成人午夜精品影院观看视频 | 亚洲欧洲视频| 国产日韩久久| 韩国成人动漫| 最近中文字幕mv在线一区二区三区四区| 成人毛片一区二区三区| 中文字幕成人av| 亚洲热在线视频| 亚洲婷婷免费| 欧美日本亚洲| 欧洲亚洲精品| 九九热视频这里只有精品| 蜜桃91麻豆精品一二三区| 婷婷综合久久一区二区三区| 亚洲精品乱码久久久久久久久久久久| 国产精品嫩草99av在线| 日韩精品一区二区三区四区五区| 777午夜精品电影免费看| 精品国产一区二区三区久久久狼| av小说天堂网| 精品日韩美女的视频高清| 久久中文字幕精品| 国产综合久久久久久鬼色| 国产中文字幕乱人伦在线观看| 奇米777国产一区国产二区| 国产精品久久久久久影视| 18视频在线观看网站| 亚洲精品mp4| 国产成人av免费| 一区二区成人在线视频| 色婷婷在线影院| 国产综合久久久久久久久久久久| 黄色一级在线视频| 三上亚洲一区二区| 国产一区二区三区色淫影院| 精品福利在线| 97视频免费在线看| 免费黄色在线网站| 日韩精品在线免费观看| 一级淫片免费看| 欧美日韩性生活视频| 日本美女黄色一级片| 99热精品国产| 99精品视频免费版的特色功能| 国产人成精品一区二区三| 天天做天天爱天天高潮| 一区二区小说| 成人毛片网站| 天天综合91| 琪琪第一精品导航| 国产亚av手机在线观看| 色综久久综合桃花网| 熟妇人妻中文av无码| 欧美日韩国产精品自在自线| 国产欧美一区二区三区在线看蜜臂| 亚洲视频一区在线观看| 一区二区精品免费| 不卡区在线中文字幕| www,av在线| 日本va欧美va精品| www.com毛片| 亚洲天堂激情| 波多野结衣 作品| 欧美国产小视频| 日韩国产精品一区二区| 亚洲精品小区久久久久久| 官网99热精品| 一区二区中文字幕在线观看| 成人在线精品视频| 国产一区高清| 国产精品久久电影观看| 天天综合av| 欧美亚洲国产视频小说| xxx性欧美| 九九热这里只有精品免费看| 黄网站视频在线观看| 中文综合在线观看| 黄色的视频在线免费观看| 日韩av在线网页| 天堂中文网在线| 亚洲成成品网站| 亚洲国产精品国自产拍久久| 日韩一区二区三区电影在线观看| 国产精品久久免费| 欧美人体做爰大胆视频| 亚洲最大成人在线视频| 欧美色欧美亚洲另类二区| 中文精品久久久久人妻不卡| 欧美日韩在线直播| 中文字幕一区二区三区四区视频 | 国产成人久久精品| 在线观看涩涩| 青青草一区二区| 亚洲精品国产嫩草在线观看| 国产精品久久久久久一区二区| 国产成人免费9x9x人网站视频| 国产不卡视频在线| 99re久久| 国产美女精品视频| 国产一区二区| 国产精品高清一区二区三区| 加勒比色老久久爱综合网| 老司机精品福利在线观看| 国产精品三级| 一本久道久久综合| 欧美+日本+国产+在线a∨观看| 无码人妻精品一区二区蜜桃百度| 狠狠色综合网| 成人一级片网站| 蜜臀a∨国产成人精品| 亚洲综合在线一区二区| 成人免费视频视频| 国产福利短视频| 中文字幕va一区二区三区| a一级免费视频| 亚洲一区二区欧美日韩| 国产精品suv一区| 欧洲视频一区二区| av天堂一区二区三区| 亚洲国产精品99| 国产福利小视频在线| 久久精品成人欧美大片古装| 污片视频在线免费观看| 538国产精品一区二区在线 | 欧美被日视频| 久久久久久国产| 户外露出一区二区三区| 国产日韩欧美一二三区| 成人在线视频你懂的| 日韩精彩视频| 欧美午夜电影在线观看 | 波多野结衣av一区二区全免费观看| 99亚洲视频| 911福利视频| 94色蜜桃网一区二区三区| 小泽玛利亚一区| 黑人狂躁日本妞一区二区三区 | 国产精品一区二区你懂的| 亚洲の无码国产の无码步美| 国产精品久久精品日日| 国产真实夫妇交换视频| 欧美色网一区二区| 在线观看xxx| 美女撒尿一区二区三区| 日韩久久一区二区三区| 国产精品对白刺激久久久| av伊人久久| 缅甸午夜性猛交xxxx| 国产精品影视网| 日本一区二区视频在线播放| 亚洲国产日韩精品| 91久久久久久久久久久久| 日韩电影免费观看中文字幕 | 日韩在线中文| 久久无码高潮喷水| 国产黄色精品网站| 蜜桃av免费观看| 色综合咪咪久久| 污污网站在线免费观看| 大量国产精品视频| 久久久加勒比| 亚洲国产日韩美| 久久久蜜桃一区二区人| 久久人人妻人人人人妻性色av| 亚洲精品乱码久久久久久| 中文字幕一区二区三区免费看| 亚洲免费av网址| 桃色av一区二区| 精品久久久久亚洲| 激情综合在线| 中文字幕永久免费| 亚洲精品自拍动漫在线| 亚洲综合视频在线播放| 这里只有精品视频| 欧美国产日韩电影| 日本一区视频在线播放| 噜噜噜躁狠狠躁狠狠精品视频| 精品无码国产一区二区三区51安| 亚洲综合区在线| 不卡的日韩av| 欧美日韩福利视频| ccyy激情综合| 妞干网在线观看视频| 不卡一卡二卡三乱码免费网站| 久久久久成人网站| 精品国产制服丝袜高跟| 呦呦在线视频| 高清不卡一区二区三区| 国产尤物精品| 大尺度做爰床戏呻吟舒畅| 亚洲国产一区视频| 污视频在线免费观看| 全球成人中文在线| 精品国产乱码久久久| 污污动漫在线观看| 亚洲欧洲日韩av| www.我爱av| 97福利一区二区| 蜜臀久久99精品久久一区二区| 50路60路老熟妇啪啪| 亚洲国产精品高清| 一区二区www| 欧美日本中文字幕| 久9re热视频这里只有精品| 亚洲熟妇av一区二区三区漫画| 久久精品夜色噜噜亚洲aⅴ| 波多野结衣日韩| 精品国产区一区二区三区在线观看| 高清一区二区| 国产精品自拍合集| 91免费视频网| 中文字幕一二区| 欧美激情精品久久久久久蜜臀| 粉嫩av一区二区| 日韩欧美精品在线观看视频| 国产精品人人做人人爽人人添| 国产又黄又大又粗的视频| 久久久久久久电影一区| 香蕉久久99| 亚洲美女性囗交| 亚洲一级二级三级| 黄色在线视频观看网站| 成人伊人精品色xxxx视频| 激情六月综合| 国内精品卡一卡二卡三| 欧美一区二区三区喷汁尤物| 蜜桃视频在线观看免费视频| 亚洲国产精品视频一区| 成人午夜视频在线| 中文字幕理论片| 国内精品小视频| 久久福利综合| 国产精品久久久免费观看| 欧美乱熟臀69xxxxxx| 人在线成免费视频| 一级日韩一区在线观看| 99久久99久久精品免费看蜜桃|