92国产精品视频_亚洲a级在线观看_国产精品电影观看_国产精品免费观看在线_精品伊人久久97_亚洲人成在线观_尤物九九久久国产精品的特点_成人激情在线播放_成人黄色大片在线免费观看_亚洲成人精品久久久_久久免费视频在线观看_久久精品国产一区_国产一区二区三区18_亚洲欧美中文字幕在线一区_日韩美女中文字幕_日韩视频免费在线

ES6新特性Promise異步調用

2018-6-27    seo達人

如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

Promise 的含義

Promise 是異步編程的一種解決方案,比傳統的解決方案–回調函數和事件--更合理和更強大。它由社區最早提出和實現,ES6將其寫進了語言標準,統一了語法,原生提供了Promise

所謂Promise ,簡單說就是一個容器,里面保存著某個未來才回結束的事件(通常是一個異步操作)的結果。從語法上說,Promise是一個對象,從它可以獲取異步操作的消息。 
Promise 對象的狀態不受外界影響

三種狀態:

  • pending:進行中
  • fulfilled :已經成功
  • rejected 已經失敗

狀態改變: 
Promise對象的狀態改變,只有兩種可能:

  • 從pending變為fulfilled
  • 從pending變為rejected。

這兩種情況只要發生,狀態就凝固了,不會再變了,這時就稱為resolved(已定型

基本用法

ES6規定,Promise對象是一個構造函數,用來生成Promise實例


    
  1. const promist = new Promise(function(resolve,reject){
  2. if(/*異步操作成功*/){
  3. resolve(value);
  4. }else{
  5. reject(error);
  6. }
  7. })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

resolve函數的作用是,將Promise對象的狀態從“未完成”變為“成功”(即從 pending 變為 resolved),在異步操作成功時調用,并將異步操作的結果,作為參數傳遞出去; 
reject函數的作用是,將Promise對象的狀態從“未完成”變為“失敗”(即從 pending 變為 rejected),在異步操作失敗時調用,并將異步操作報出的錯誤,作為參數傳遞出去。

Promise的源碼分析:

1.回調地獄

曾幾何時,我們的代碼是這樣的,為了拿到回調的結果,不得不callback hell,這種環環相扣的代碼可以說是相當惡心了


            
  1. let fs = require('fs')
  2. fs.readFile('./a.txt','utf8',function(err,data){
  3. fs.readFile(data,'utf8',function(err,data){
  4. fs.readFile(data,'utf8',function(err,data){
  5. console.log(data)
  6. })
  7. })
  8. })

終于,我們的蓋世英雄出現了,他身披金甲圣衣、駕著七彩祥云。好吧打岔兒了,沒錯他就是我們的Promise,那讓我們來看看用了Promise之后,上面的代碼會變成什么樣吧


            
  1. let fs = require('fs')
  2. function read(url){
  3. return new Promise((resolve,reject)=>{
  4. fs.readFile(url,'utf8',function(error,data){
  5. error && reject(error)
  6. resolve(data)
  7. })
  8. })
  9. }
  10. read('./a.txt').then(data=>{
  11. return read(data)
  12. }).then(data=>{
  13. return read(data)
  14. }).then(data=>{
  15. console.log(data)
  16. })

2.重點開始,小眼睛都看過來

2.1 Promise/A+

首先我們要知道自己手寫一個Promise,應該怎么去寫,誰來告訴我們怎么寫,需要遵循什么樣的規則。當然這些你都不用擔心,其實業界都是通過一個規則指標來生產Promise的。讓我們來看看是什么東西。傳送門?Promise/A+

2.2 constructor

我們先聲明一個類,叫做Promise,里面是構造函數。如果es6還有問題的可以去阮大大的博客上學習一下(傳送門?es6


            
  1. class Promise{
  2. constructor(executor){
  3. //控制狀態,使用了一次之后,接下來的都不被使用
  4. this.status = 'pendding'
  5. this.value = undefined
  6. this.reason = undefined
  7. //定義resolve函數
  8. let resolve = (data)=>{
  9. //這里pendding,主要是為了防止executor中調用了兩次resovle或reject方法,而我們只調用一次
  10. if(this.status==='pendding'){
  11. this.status = 'resolve'
  12. this.value = data
  13. }
  14. }
  15. //定義reject函數
  16. let reject = (data)=>{
  17. if(this.status==='pendding'){
  18. this.status = 'reject'
  19. this.reason = data
  20. }
  21. }
  22. //executor方法可能會拋出異常,需要捕獲
  23. try{
  24. //將resolve和reject函數給使用者
  25. executor(resolve,reject)
  26. }catch(e){
  27. //如果在函數中拋出異常則將它注入reject中
  28. reject(e)
  29. }
  30. }
  31. }

那么接下來我會分析上面代碼的作用,原理

  • executor:這是實例Promise對象時在構造器中傳入的參數,一般是一個function(resolve,reject){}
  • status:``Promise的狀態,一開始是默認的pendding狀態,每當調用道resolve和reject方法時,就會改變其值,在后面的then方法中會用到
  • value:resolve回調成功后,調用resolve方法里面的參數值
  • reason:reject回調成功后,調用reject方法里面的參數值
  • resolve:聲明resolve方法在構造器內,通過傳入的executor方法傳入其中,用以給使用者回調
  • reject:聲明reject方法在構造器內,通過傳入的executor方法傳入其中,用以給使用者回調

2.3 then

then方法是Promise中最為重要的方法,他的用法大家都應該已經知道,就是將Promise中的resolve或者reject的結果拿到,那么我們就能知道這里的then方法需要兩個參數,成功回調和失敗回調,上代碼!


            
  1. then(onFufilled,onRejected){
  2. if(this.status === 'resolve'){
  3. onFufilled(this.value)
  4. }
  5. if(this.status === 'reject'){
  6. onRejected(this.reason)
  7. }
  8. }

這里主要做了將構造器中resolve和reject的結果傳入onFufilledonRejected中,注意這兩個是使用者傳入的參數,是個方法。所以你以為這么簡單就完了?要想更Swag的應對各種場景,我們必須得再完善。繼續往下走!

3.異步的Promise

之前我們只是處理了同步情況下的Promise,簡而言之所有操作都沒有異步的成分在內。那么如果是異步該怎么辦?

3.1 callback!?。?!

最早處理異步的方法就是callback,就相當于我讓你幫我掃地,我會在給你發起任務時給你一個手機,之后我做自己的事情去,不用等你,等你掃完地就會打手機給我,誒,我就知道了地掃完了。這個手機就是callback,回調函數。

首先我們需要改一下構造器里的代碼,分別添加兩個回調函數的數組,分別對應成功回調和失敗回調。他們的作用是當成功執行resolve或reject時,執行callback。


            
  1. //存放成功回調的函數
  2. this.onResolvedCallbacks = []
  3. //存放失敗回調的函數
  4. this.onRejectedCallbacks = []
  5. let resolve = (data)=>{
  6. if(this.status==='pendding'){
  7. this.status = 'resolve'
  8. this.value = data
  9. //監聽回調函數
  10. this.onResolvedCallbacks.forEach(fn=>fn())
  11. }
  12. }
  13. let reject = (data)=>{
  14. if(this.status==='pendding'){
  15. this.status = 'reject'
  16. this.reason = data
  17. this.onRejectedCallbacks.forEach(fn=>fn())
  18. }
  19. }

然后是then需要多加一個狀態判斷,當Promise中是異步操作時,需要在我們之前定義的回調函數數組中添加一個回調函數。


            
  1. if(this.status === 'pendding'){
  2. this.onResolvedCallbacks.push(()=>{
  3. // to do....
  4. let x = onFufilled(this.value)
  5. resolvePromise(promise2,x,resolve,reject)
  6. })
  7. this.onRejectedCallbacks.push(()=>{
  8. let x = onRejected(this.reason)
  9. resolvePromise(promise2,x,resolve,reject)
  10. })
  11. }

ok!大功告成,異步已經解決了

3.2 resolvePromise

這也是Promise中的重頭戲,我來介紹一下,我們在用Promise的時候可能會發現,當then函數中return了一個值,我們可以繼續then下去,不過是什么值,都能在下一個then中獲取,還有,當我們不在then中放入參數,例:promise.then().then(),那么其后面的then依舊可以得到之前then返回的值,可能你現在想很迷惑。讓我來解開你心中的憂愁,follow me。


            
  1. then(onFufilled,onRejected){
  2. //解決onFufilled,onRejected沒有傳值的問題
  3. onFufilled = typeof onFufilled === 'function'?onFufilled:y=>y
  4. //因為錯誤的值要讓后面訪問到,所以這里也要跑出個錯誤,不然會在之后then的resolve中捕獲
  5. onRejected = typeof onRejected === 'function'?onRejected:err=>{ throw err ;}
  6. //聲明一個promise對象
  7. let promise2
  8. if(this.status === 'resolve'){
  9. //因為在.then之后又是一個promise對象,所以這里肯定要返回一個promise對象
  10. promise2 = new Promise((resolve,reject)=>{
  11. setTimeout(()=>{
  12. //因為穿透值的緣故,在默認的跑出一個error后,不能再用下一個的reject來接受,只能通過try,catch
  13. try{
  14. //因為有的時候需要判斷then中的方法是否返回一個promise對象,所以需要判斷
  15. //如果返回值為promise對象,則需要取出結果當作promise2的resolve結果
  16. //如果不是,直接作為promise2的resolve結果
  17. let x = onFufilled(this.value)
  18. //抽離出一個公共方法來判斷他們是否為promise對象
  19. resolvePromise(promise2,x,resolve,reject)
  20. }catch(e){
  21. reject(e)
  22. }
  23. },0)
  24. })
  25. }
  26. if(this.status === 'reject'){
  27. promise2 = new Promise((resolve,reject)=>{
  28. setTimeout(()=>{
  29. try{
  30. let x = onRejected(this.reason)
  31. resolvePromise(promise2,x,resolve,reject)
  32. }catch(e){
  33. reject(e)
  34. }
  35. },0)
  36. })
  37. }
  38. if(this.status === 'pendding'){
  39. promise2 = new Promise((resolve,reject)=>{
  40. this.onResolvedCallbacks.push(()=>{
  41. // to do....
  42. setTimeout(()=>{
  43. try{
  44. let x = onFufilled(this.value)
  45. resolvePromise(promise2,x,resolve,reject)
  46. }catch(e){
  47. reject(e)
  48. }
  49. },0)
  50. })
  51. this.onRejectedCallbacks.push(()=>{
  52. setTimeout(()=>{
  53. try{
  54. let x = onRejected(this.reason)
  55. resolvePromise(promise2,x,resolve,reject)
  56. }catch(e){
  57. reject(e)
  58. }
  59. })
  60. })
  61. })
  62. }
  63. return promise2
  64. }

一下子多了很多方法,不用怕,我會一一解釋

  1. 返回Promise?:首先我們要注意的一點是,then有返回值,then了之后還能在then,那就說明之前的then返回的必然是個Promise
  2. 為什么外面要包一層setTimeout?:因為Promise本身是一個異步方法,屬于微任務一列,必須得在執行棧執行完了在去取他的值,所以所有的返回值都得包一層異步setTimeout。
  3. 為什么開頭有兩個判斷?:這就是之前想要解決的如果then函數中的參數不是函數,那么我們需要做處理。如果onFufilled不是函數,就需要自定義個函數用來返回之前resolve的值,如果onRejected不是函數,自定義個函數拋出異常。這里會有個小坑,如果這里不拋出異常,會在下一個then的onFufilled中拿到值。又因為這里拋出了異常所以所有的onFufilled或者onRejected都需要try/catch,這也是Promise/A+的規范。當然本人覺得成功的回調不需要拋出異常也可以,大家可以仔細想想。
  4. resolvePromise是什么?:這其實是官方Promise/A+的需求。因為你的then可以返回任何職,當然包括Promise對象,而如果是Promise對象,我們就需要將他拆解,直到它不是一個Promise對象,取其中的值。

那就讓我們來看看這個resolvePromise到底長啥樣。


            
  1. function resolvePromise(promise2,x,resolve,reject){
  2. //判斷x和promise2之間的關系
  3. //因為promise2是上一個promise.then后的返回結果,所以如果相同,會導致下面的.then會是同一個promise2,一直都是,沒有盡頭
  4. if(x === promise2){//相當于promise.then之后return了自己,因為then會等待return后的promise,導致自己等待自己,一直處于等待
  5. return reject(new TypeError('循環引用'))
  6. }
  7. //如果x不是null,是對象或者方法
  8. if(x !== null && (typeof x === 'object' || typeof x === 'function')){
  9. //為了判斷resolve過的就不用再reject了,(比如有reject和resolve的時候)
  10. let called
  11. try{//防止then出現異常,Object.defineProperty
  12. let then = x.then//取x的then方法可能會取到{then:{}},并沒有執行
  13. if(typeof then === 'function'){
  14. //我們就認為他是promise,call他,因為then方法中的this來自自己的promise對象
  15. then.call(x,y=>{//第一個參數是將x這個promise方法作為this指向,后兩個參數分別為成功失敗回調
  16. if(called) return;
  17. called = true
  18. //因為可能promise中還有promise,所以需要遞歸
  19. resolvePromise(promise2,y,resolve,reject)
  20. },err=>{
  21. if(called) return;
  22. called = true
  23. //一次錯誤就直接返回
  24. reject(err)
  25. })
  26. }else{
  27. //如果是個普通對象就直接返回resolve作為結果
  28. resolve(x)
  29. }
  30. }catch(e){
  31. if(called) return;
  32. called = true
  33. reject(e)
  34. }
  35. }else{
  36. //這里返回的是非函數,非對象的值,就直接放在promise2的resolve中作為結果
  37. resolve(x)
  38. }
  39. }

它的作用是用來將onFufilled的返回值進行判斷取值處理,把最后獲得的值放入最外面那層的Promise的resolve函數中。

  1. 參數promise2(then函數返回的Promise對象),x(onFufilled函數的返回值),resolve、reject(最外層的Promise上的resolve和reject)。
  2. 為什么要在一開始判斷promise2x?:首先在Promise/A+中寫了需要判斷這兩者如果相等,需要拋出異常,我就來解釋一下為什么,如果這兩者相等,我們可以看下下面的例子,第一次p2是p1.then出來的結果是個Promise對象,這個Promise對象在被創建的時候調用了resolvePromise(promise2,x,resolve,reject)函數,又因為x等于其本身,是個Promise,就需要then方法遞歸它,直到他不是Promise對象,但是x(p2)的結果還在等待,他卻想執行自己的then方法,就會導致等待。

            
  1. let p1 = new Promise((resolve,reject)=>{
  2. resolve()
  3. })
  4. let p2 = p1.then(d=>{
  5. return p2
  6. })
  1. called是用來干嘛的?:called變量主要是用來判斷如果resolvePromise函數已經resolve或者reject了,那就不需要在執行下面的resolce或者reject。
  2. 為什么取then這個屬性?:因為我們需要去判斷x是否為Promise,then屬性如果為普通值,就直接resolve掉,如果是個function,就是Promise對象,之后我們就需要將這個x的then方法進行執行,用call的原因是因為then方法里面this指向的問題。
  3. 為什么要遞歸去調用resolvePromise函數?:相信細心的人已經發現了,我這里使用了遞歸調用法,首先這是Promise/A+中要求的,其次是業務場景的需求,當我們碰到那種Promise的resolve里的Promise的resolve里又包了一個Promise的話,就需要遞歸取值,直到x不是Promise對象。

4.完善Promise

我們現在已經基本完成了Promise的then方法,那么現在我們需要看看他的其他方法。

4.1 catch

相信大家都知道catch這個方法是用來捕獲Promise中的reject的值,也就是相當于then方法中的onRejected回調函數,那么問題就解決了。我們來看代碼。


            
  1. //catch方法
  2. catch(onRejected){
  3. return this.then(null,onRejected)
  4. }

該方法是掛在Promise原型上的方法。當我們調用catch傳callback的時候,就相當于是調用了then方法。

4.2 resolve/reject

大家一定都看到過Promise.resolve()、Promise.reject()這兩種用法,它們的作用其實就是返回一個Promise對象,我們來實現一下。


            
  1. //resolve方法
  2. Promise.resolve = function(val){
  3. return new Promise((resolve,reject)=>{
  4. resolve(val)
  5. })
  6. }
  7. //reject方法
  8. Promise.reject = function(val){
  9. return new Promise((resolve,reject)=>{
  10. reject(val)
  11. })
  12. }

這兩個方法是直接可以通過class調用的,原理就是返回一個內部是resolve或reject的Promise對象。

4.3 all

all方法可以說是Promise中很常用的方法了,它的作用就是將一個數組的Promise對象放在其中,當全部resolve的時候就會執行then方法,當有一個reject的時候就會執行catch,并且他們的結果也是按著數組中的順序來排放的,那么我們來實現一下。


            
  1. //all方法(獲取所有的promise,都執行then,把結果放到數組,一起返回)
  2. Promise.all = function(promises){
  3. let arr = []
  4. let i = 0
  5. function processData(index,data){
  6. arr[index] = data
  7. i++
  8. if(i == promises.length){
  9. resolve(arr)
  10. }
  11. }
  12. return new Promise((resolve,reject)=>{
  13. for(let i=0;i<promises.length;i++){
  14. promises[i].then(data=>{
  15. processData(i,data)
  16. },reject)
  17. }
  18. })
  19. }

其原理就是將參數中的數組取出遍歷,每當執行成功都會執行processData方法,processData方法就是用來記錄每個Promise的值和它對應的下標,當執行的次數等于數組長度時就會執行resolve,把arr的值給then。這里會有一個坑,如果你是通過arr數組的長度來判斷他是否應該resolve的話就會出錯,為什么呢?因為js數組的特性,導致如果先出來的是1位置上的值進arr,那么0位置上也會多一個空的值,所以不合理。

4.4 race

race方法雖然不常用,但是在Promise方法中也是一個能用得上的方法,它的作用是將一個Promise數組放入race中,哪個先執行完,race就直接執行完,并從then中取值。我們來實現一下吧。


            
  1. //race方法
  2. Promise.race = function(promises){
  3. return new Promise((resolve,reject)=>{
  4. for(let i=0;i<promises.length;i++){
  5. promises[i].then(resolve,reject)
  6. }
  7. })
  8. }

原理大家應該看懂了,很簡單,就是遍歷數組執行Promise,如果有一個Promise執行成功就resolve。

Promise語法糖 deferred

語法糖這三個字大家一定很熟悉,作為一個很Swag的前端工程師,對async/await這對兄弟肯定很熟悉,沒錯他們就是generator的語法糖。而我們這里要講的語法糖是Promise的。


            
  1. //promise語法糖 也用來測試
  2. Promise.deferred = Promise.defer = function(){
  3. let dfd = {}
  4. dfd.promise = new Promise((resolve,reject)=>{
  5. dfd.resolve = resolve
  6. dfd.reject = reject
  7. })
  8. return dfd
  9. }

什么作用呢?看下面代碼你就知道了


            
  1. let fs = require('fs')
  2. let Promise = require('./promises')
  3. //Promise上的語法糖,為了防止嵌套,方便調用
  4. //壞處 錯誤處理不方便
  5. function read(){
  6. let defer = Promise.defer()
  7. fs.readFile('./1.txt','utf8',(err,data)=>{
  8. if(err)defer.reject(err)
  9. defer.resolve(data)
  10. })
  11. return defer.Promise
  12. }

沒錯,我們可以方便的去調用他語法糖defer中的Promise對象。那么它還有沒有另外的方法呢?答案是有的。我們需要在全局上安裝promises-aplus-tests插件npm i promises-aplus-tests -g,再輸入promises-aplus-tests [js文件名] 即可驗證你的Promise的規范。


藍藍設計www.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務


日歷

鏈接

個人資料

藍藍設計的小編 http://www.skdbbs.com

存檔

92国产精品视频_亚洲a级在线观看_国产精品电影观看_国产精品免费观看在线_精品伊人久久97_亚洲人成在线观_尤物九九久久国产精品的特点_成人激情在线播放_成人黄色大片在线免费观看_亚洲成人精品久久久_久久免费视频在线观看_久久精品国产一区_国产一区二区三区18_亚洲欧美中文字幕在线一区_日韩美女中文字幕_日韩视频免费在线
国产91对白在线播放| 久久影院模特热| 久久久久久久999精品视频| 欧美精品videofree1080p| 在线观看精品自拍私拍| 国产91精品久久久久| 久久久久国产精品一区| 欧美国产在线电影| 亚洲国产成人精品电影| 欧美黑人性猛交| 亚洲高清不卡av| 美女久久久久久久久久久| 国产精品pans私拍| 亚洲日本中文字幕免费在线不卡| 日本不卡视频在线播放| 精品亚洲一区二区三区四区五区| 精品国产一区二区三区久久| 色偷偷偷综合中文字幕;dd| 国产一区二区黄| 国产精品无码专区在线观看| 色www亚洲国产张柏芝| 国产成人97精品免费看片| 久久久视频免费观看| 亚洲天堂av女优| 精品视频www| 欧美一区二区三区免费视| 2019中文字幕全在线观看| 日韩欧美一区二区三区久久| 少妇高潮 亚洲精品| 性欧美视频videos6一9| 亚洲精品不卡在线| 最近2019免费中文字幕视频三| 97人洗澡人人免费公开视频碰碰碰| 97精品视频在线播放| 97视频在线观看亚洲| 一区二区亚洲精品国产| 亚洲一区999| 亚洲最大成人网色| 国产视频丨精品|在线观看| 日韩欧美在线看| 亚洲视频网站在线观看| 91亚洲精品在线观看| 成人免费大片黄在线播放| 亚洲国产三级网| 欧美中文字幕在线| 国产精品成人品| 一区二区三区高清国产| 亚洲国产精品大全| 成人国产精品一区二区| 久久久久久久电影一区| 日韩在线观看免费| 亚洲国产福利在线| 欧美国产激情18| 日韩电影免费在线观看| 狠狠躁天天躁日日躁欧美| 精品国产福利视频| 性亚洲最疯狂xxxx高清| 伊人伊成久久人综合网小说| 日韩a**中文字幕| 日韩精品在线观看一区二区| 欧美激情性做爰免费视频| 亚洲国产日韩欧美综合久久| 久久久99免费视频| 欧美日韩国产丝袜另类| 亚洲白拍色综合图区| 这里只有精品视频在线| 福利二区91精品bt7086| www.xxxx欧美| 欧美日韩成人精品| 日韩中文字幕第一页| 亚洲乱亚洲乱妇无码| 国产精品99久久99久久久二8| 精品性高朝久久久久久久| 欧美日韩中国免费专区在线看| 久久久这里只有精品视频| 国产精品jizz在线观看麻豆| 欧美成aaa人片在线观看蜜臀| 国a精品视频大全| 中文字幕亚洲专区| 26uuu另类亚洲欧美日本一| 国产精品丝袜视频| 日韩激情视频在线| 国产深夜精品福利| 午夜精品99久久免费| 日韩亚洲国产中文字幕| 最近2019中文字幕mv免费看| 欧美日韩中文字幕综合视频| 久久青草精品视频免费观看| 色综久久综合桃花网| 亚洲自拍中文字幕| 国产精品高潮呻吟久久av无限| 国产精品日日做人人爱| 91亚洲va在线va天堂va国| 国产不卡av在线| 国产999在线观看| 中文亚洲视频在线| 91精品国产91久久久久福利| 亚洲老头老太hd| 国产成人综合亚洲| 日韩福利伦理影院免费| 日韩va亚洲va欧洲va国产| 欧美最顶级丰满的aⅴ艳星| 国产精品xxx视频| 668精品在线视频| 日韩成人性视频| 精品二区三区线观看| 欧美在线xxx| 成人欧美在线视频| 欧美大尺度激情区在线播放| 国产成人精品一区二区| 中文字幕亚洲色图| 国产精品视频永久免费播放| 日韩免费在线免费观看| 国产91精品最新在线播放| 久久精品在线播放| 欧洲s码亚洲m码精品一区| 亚洲xxx自由成熟| 日韩福利伦理影院免费| 91免费人成网站在线观看18| 国产日产亚洲精品| 欧美国产日产韩国视频| 精品久久久久久| 国产主播欧美精品| 国产成人精品一区二区在线| 欧美寡妇偷汉性猛交| 色777狠狠综合秋免鲁丝| 7777精品久久久久久| 精品高清美女精品国产区| 精品日本美女福利在线观看| 欧美电影免费观看网站| 亚洲电影第1页| 国产精品女人久久久久久| 视频直播国产精品| 91精品久久久久久久久久久久久久| 久久久免费av| 中文字幕av一区| 久久精品电影网站| 亚洲国产精品福利| 欧美日韩在线免费观看| 久久福利视频网| 97视频人免费观看| 精品久久久久久久久久久久久| 日韩在线小视频| 欧美日韩xxxxx| 黄色91在线观看| 国产日韩精品综合网站| 日韩视频在线免费| 日韩av免费一区| 久久综合免费视频| 亚洲一区二区久久久| 九九久久国产精品| 久久久久久91香蕉国产| 色婷婷av一区二区三区久久| 精品激情国产视频| 日韩欧美在线字幕| 日韩电影免费在线观看中文字幕| 成人www视频在线观看| 欧美国产精品va在线观看| 亚洲欧美视频在线| 欧美成人h版在线观看| 欧美精品精品精品精品免费| 奇门遁甲1982国语版免费观看高清| 亚洲午夜精品久久久久久久久久久久| 91精品久久久久久久久久久久久|