亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

node使用promise替代回調函數

2024-05-06 16:44:09
字體:
來源:轉載
供稿:網友

在學習 Node.js 過程中接觸到了如何使用 async 來控制并發(使用 async 控制并發

async 的本質是一個流程控制。其實在異步編程中,還有一個更為經典的模型,叫做 Promise/Deferred 模型(當然還有更多相關解決方法,比如 eventproxy,co 等,到時候遇到在挖坑)

首先,我們思考一個典型的異步編程模型,考慮這樣一個題目:讀取一個文件,在控制臺輸出這個文件內容

var fs = require('fs');fs.readFile('1.txt', 'utf8', function (err, data) {  console.log(data);});

看起來很簡單,再進一步: 讀取兩個文件,在控制臺輸出這兩個文件內容

var fs = require('fs');fs.readFile('1.txt', 'utf8', function (err, data) {  console.log(data);  fs.readFile('2.txt', 'utf8', function (err, data) {    console.log(data);  });});

要是讀取更多的文件呢

var fs = require('fs');fs.readFile('1.txt', 'utf8', function (err, data) {  fs.readFile('2.txt', 'utf8', function (err, data) {    fs.readFile('3.txt', 'utf8', function (err, data) {      fs.readFile('4.txt', 'utf8', function (err, data) {        // ...      });    });  });});

這就是傳說中的 callback hell,可以使用 async 來改善這段代碼,但是在本例中我們要用 promise/defer 來改善它

promise 基本概念

首先它是一個對象,它和 javascript 普通的對象沒什么區別,同時,它也是一種規范,跟異步操作約定了統一的接口,表示一個異步操作的最終結果,以同步的方式來寫代碼,執行的操作是異步的,但又保證程序執行的順序是同步的

1. promise 只有三種狀態,未完成,完成 (fulfilled) 和失敗 (rejected)

2. promise 的狀態可以由未完成轉換成完成,或者未完成轉換成失敗

3. promise 的狀態轉換只發生一次

promise 有一個 then 方法,then 方法可以接受 3 個函數作為參數。前兩個函數對應 promise 的兩種狀態 fulfilled, rejected 的回調函數。第三個函數用于處理進度信息

為了理解它,一些重要原理必須記牢:.then() 總是返回一個新的 promise,如下面代碼:

var promise = readFile()var promise2 = promise.then(readAnotherFile, console.error)

這里 then 的參數 readAnotherFile, console.error 是代表異步操作成功后的動作 onFulfilled 或失敗后的動作 OnRejected,也就是說,讀取文件成功后執行 readAnotherFile 函數,否則失敗打印記錄錯誤。這種實現是兩個中只有一種可能

也可以理解為:

promiseSomething().then(function (fulfilled) {  // 當 promise 狀態變成 fulfilled 時,調用此函數}, function (rejected) {  // 當 promise 狀態變成 rejected 時,調用此函數}, function (progress) {  // 當返回進度信息時,調用此函數});

Promise 法則有兩部分必須分離:

1. then() 總是返回一個新的 promise,每次你調用它,它不管回調做什么,因為 .then() 在回調被調用之前已經給了你一個承諾 promise,回調的行為只影響承諾 promise 的實施,如果回調返回一個值,那么 promise 將使用那個值,如果這個值是一個 promise,返回這個 promise 實施后的值給這個值,如果回調拋出錯誤,promise 將拒絕錯誤

2. 被 .then() 返回的 promise 是一個新的 promise ,它不同于那些 .then() 被調用的 promise,promise 長長的鏈條有時會好些隱藏這個事實,不管如何,每次 .then() 調用都會產生一個新的 promise,這里必須注意的是你真正需要考慮的是你最后調用 .then() 可能代表失敗,那么如果你不捕獲這種失敗,那么容易導致你的錯誤 exception 消失

來看一個利用 q 來處理這種問題的簡單例子:

var Q = require('q');var defer = Q.defer();/** * 獲取初始 promise * @private */function getInitialPromise() {  return defer.promise;} /** * 為 promise 設置三種狀態的回調函數 */getInitialPromise().then(function (success) {  console.log(success);}, function (error) {  console.log(error);}, function (progress) {  console.log(progress);});defer.notify('in progress'); // 控制臺打印 in progressdefer.resolve('resolve');   // 控制臺打印 resolvedefer.reject('reject');    // 沒有輸出。promise 的狀態只能改變一次

promise 的傳遞

then 方法會返回一個 promise,在下面這個例子中,我們用 outputPromise 指向 then 返回的 promise。

var outputPromise = getInputPromise().then(function (fulfilled) {   }, function (rejected) {   });

現在 outputPromise 就變成了受 function(fulfilled) 或者 function(rejected) 控制狀態的 promise 了。直白的意思就是:當 function(fulfilled) 或者 function(rejected) 返回一個值,比如一個字符串,數組,對象等等,那么 outputPromise 的狀態就會變成 fulfilled。

在下面這個例子中,我們可以看到,當我們把 inputPromise 的狀態通過 defer.resovle() 變成 fulfilled 時,控制臺輸出 fulfilled.

當我們把 inputPromise 的狀態通過 defer.reject() 變成 rejected,控制臺輸出 rejected

var Q = require('q');var defer = Q.defer();/** * 通過 defer 獲得 promise * @private */function getInputPromise() {  return defer.promise;} /** * 當 inputPromise 狀態由未完成變成 fulfil 時,調用 function(fulfilled) * 當 inputPromise 狀態由未完成變成 rejected 時,調用 function(rejected) * 將 then 返回的 promise 賦給 outputPromise * function(fulfilled) 和 function(rejected) 通過返回字符串將 outputPromise 的狀態由 * 未完成改變為 fulfilled * @private */var outputPromise = getInputPromise().then(function (fulfilled) {  return 'fulfilled';}, function (rejected) {  return 'rejected';}); /** * 當 outputPromise 狀態由未完成變成 fulfil 時,調用 function(fulfilled),控制臺打印 'fulfilled: fulfilled'。 * 當 outputPromise 狀態由未完成變成 rejected, 調用 function(rejected), 控制臺打印 'rejected: rejected'。 */outputPromise.then(function (fulfilled) {  console.log('fulfilled: ' + fulfilled);}, function (rejected) {  console.log('rejected: ' + rejected);}); /** * 將 inputPromise 的狀態由未完成變成 rejected */defer.reject(); // 輸出 fulfilled: rejected /** * 將 inputPromise 的狀態由未完成變成 fulfilled *///defer.resolve(); // 輸出 fulfilled: fulfilled

當 function(fulfilled) 或者 function(rejected) 拋出異常時,那么 outputPromise 的狀態就會變成 rejected

var Q = require('q');var fs = require('fs');var defer = Q.defer(); /** * 通過 defer 獲得 promise * @private */function getInputPromise() {  return defer.promise;} /** * 當 inputPromise 狀態由未完成變成 fulfil 時,調用 function(fulfilled) * 當 inputPromise 狀態由未完成變成 rejected 時,調用 function(rejected) * 將 then 返回的 promise 賦給 outputPromise * function(fulfilled) 和 function(rejected) 通過拋出異常將 outputPromise 的狀態由 * 未完成改變為 reject * @private */var outputPromise = getInputPromise().then(function (fulfilled) {  throw new Error('fulfilled');}, function (rejected) {  throw new Error('rejected');}); /** * 當 outputPromise 狀態由未完成變成 fulfil 時,調用 function(fulfilled)。 * 當 outputPromise 狀態由未完成變成 rejected, 調用 function(rejected)。 */outputPromise.then(function (fulfilled) {  console.log('fulfilled: ' + fulfilled);}, function (rejected) {  console.log('rejected: ' + rejected);}); /** * 將 inputPromise 的狀態由未完成變成 rejected */defer.reject();   // 控制臺打印 rejected [Error:rejected] /** * 將 inputPromise 的狀態由未完成變成 fulfilled *///defer.resolve(); // 控制臺打印 rejected [Error:fulfilled]

當 function(fulfilled) 或者 function(rejected) 返回一個 promise 時,outputPromise 就會成為這個新的 promise.

這樣做的意義在于聚合結果 (Q.all),管理延時,異?;謴偷鹊?/p>

比如說我們想要讀取一個文件的內容,然后把這些內容打印出來。可能會寫出這樣的代碼:

// 錯誤的寫法var outputPromise = getInputPromise().then(function (fulfilled) {  fs.readFile('test.txt', 'utf8', function (err, data) {    return data;  });});

然而這樣寫是錯誤的,因為 function(fulfilled) 并沒有返回任何值。需要下面的方式:

var Q = require('q');var fs = require('fs');var defer = Q.defer(); /** * 通過 defer 獲得promise * @private */function getInputPromise() {  return defer.promise;} /** * 當 inputPromise 狀態由未完成變成 fulfil時,調用 function(fulfilled) * 當 inputPromise 狀態由未完成變成 rejected時,調用 function(rejected) * 將 then 返回的 promise 賦給 outputPromise * function(fulfilled) 將新的 promise 賦給 outputPromise * 未完成改變為 reject * @private */var outputPromise = getInputPromise().then(function (fulfilled) {  var myDefer = Q.defer();  fs.readFile('test.txt', 'utf8', function (err, data) {    if (!err && data) {      myDefer.resolve(data);    }  });  return myDefer.promise;}, function (rejected) {  throw new Error('rejected');}); /** * 當 outputPromise 狀態由未完成變成 fulfil 時,調用 function(fulfilled),控制臺打印 test.txt 文件內容。 * */outputPromise.then(function (fulfilled) {  console.log(fulfilled);}, function (rejected) {  console.log(rejected);}); /** * 將 inputPromise 的狀態由未完成變成 rejected *///defer.reject(); /** * 將 inputPromise 的狀態由未完成變成 fulfilled */defer.resolve(); // 控制臺打印出 test.txt 的內容

方法傳遞

方法傳遞有些類似于 Java 中的 try 和 catch。當一個異常沒有響應的捕獲時,這個異常會接著往下傳遞

方法傳遞的含義是當一個狀態沒有響應的回調函數,就會沿著 then 往下找

沒有提供 function(rejected)

var outputPromise = getInputPromise().then(function (fulfilled) { })

如果 inputPromise 的狀態由未完成變成 rejected, 此時對 rejected 的處理會由 outputPromise 來完成

var Q = require('q');var fs = require('fs');var defer = Q.defer();/** * 通過defer獲得promise * @private */function getInputPromise() {  return defer.promise;} /** * 當 inputPromise 狀態由未完成變成 fulfil 時,調用 function(fulfilled) * 當 inputPromise 狀態由未完成變成 rejected 時,這個 rejected 會傳向 outputPromise */var outputPromise = getInputPromise().then(function (fulfilled) {  return 'fulfilled'});outputPromise.then(function (fulfilled) {  console.log('fulfilled: ' + fulfilled);}, function (rejected) {  console.log('rejected: ' + rejected);}); /** * 將 inputPromise 的狀態由未完成變成 rejected */defer.reject('inputpromise rejected'); // 控制臺打印 rejected: inputpromise rejected /** * 將 inputPromise的狀態由未完成變成fulfilled *///defer.resolve();

沒有提供 function(fulfilled)

var outputPromise = getInputPromise().then(null, function (rejected) { })

如果 inputPromise 的狀態由未完成變成 fulfilled, 此時對 fulfil 的處理會由 outputPromise 來完成

var Q = require('q');var fs = require('fs');var defer = Q.defer(); /** * 通過defer獲得promise * @private */function getInputPromise() {  return defer.promise;} /** * 當 inputPromise 狀態由未完成變成 fulfil時,傳遞給 outputPromise * 當 inputPromise 狀態由未完成變成 rejected時,調用 function(rejected) * function(fulfilled) 將新的 promise 賦給 outputPromise * 未完成改變為 reject * @private */var outputPromise = getInputPromise().then(null, function (rejected) {  return 'rejected';}); outputPromise.then(function (fulfilled) {  console.log('fulfilled: ' + fulfilled);}, function (rejected) {  console.log('rejected: ' + rejected);}); /** * 將 inputPromise 的狀態由未完成變成 rejected */// defer.reject('inputpromise rejected'); /** * 將 inputPromise 的狀態由未完成變成fulfilled */defer.resolve('inputpromise fulfilled'); // 控制臺打印fulfilled: inputpromise fulfilled

可以使用 fail(function(error)) 來專門針對錯誤處理,而不是使用 then(null,function(error))

var outputPromise = getInputPromise().fail(function (error) { })

看這個例子:

var Q = require('q');var fs = require('fs');var defer = Q.defer();/** * 通過defer獲得promise * @private */function getInputPromise() {  return defer.promise;} /** * 當 inputPromise 狀態由未完成變成 fulfil 時,調用 then(function(fulfilled)) * 當 inputPromise 狀態由未完成變成 rejected 時,調用 fail(function(error)) * function(fulfilled) 將新的 promise 賦給 outputPromise * 未完成改變為reject * @private */var outputPromise = getInputPromise().then(function (fulfilled) {  return fulfilled;}).fail(function (error) {  console.log('fail: ' + error);});/** * 將 inputPromise 的狀態由未完成變成 rejected */defer.reject('inputpromise rejected');// 控制臺打印 fail: inputpromise rejected /** * 將 inputPromise 的狀態由未完成變成 fulfilled *///defer.resolve('inputpromise fulfilled');

可以使用 progress(function (progress)) 來專門針對進度信息進行處理,而不是使用 then(function (success) { }, function (error) { }, function (progress) { })

var Q = require('q');var defer = Q.defer();/** * 獲取初始 promise * @private */function getInitialPromise() {  return defer.promise;}/** * 為 promise 設置 progress 信息處理函數 */var outputPromise = getInitialPromise().then(function (success) { }).progress(function (progress) {  console.log(progress);}); defer.notify(1);defer.notify(2); // 控制臺打印 1,2

promise 鏈

promise 鏈提供了一種讓函數順序執行的方法

函數順序執行是很重要的一個功能。比如知道用戶名,需要根據用戶名從數據庫中找到相應的用戶,然后將用戶信息傳給下一個函數進行處理

var Q = require('q');var defer = Q.defer();// 一個模擬數據庫var users = [{ 'name': 'andrew', 'passwd': 'password' }];function getUsername() {  return defer.promise;} function getUser(username) {  var user;  users.forEach(function (element) {    if (element.name === username) {      user = element;    }  });  return user;} // promise 鏈getUsername().then(function (username) {  return getUser(username);}).then(function (user) {  console.log(user);}); defer.resolve('andrew');

我們通過兩個 then 達到讓函數順序執行的目的。

then 的數量其實是沒有限制的。當然,then 的數量過多,要手動把他們鏈接起來是很麻煩的。比如

foo(initialVal).then(bar).then(baz).then(qux)

這時我們需要用代碼來動態制造 promise 鏈

var funcs = [foo, bar, baz, qux]var result = Q(initialVal) funcs.forEach(function (func) {  result = result.then(func)})return result

當然,我們可以再簡潔一點

var funcs = [foo, bar, baz, qux]funcs.reduce(function (pre, current),Q(initialVal){  return pre.then(current)})

看一個具體的例子

function foo(result) {  console.log(result);  return result + result;} // 手動鏈接Q('hello').then(foo).then(foo).then(foo); // 控制臺輸出: hello// hellohello// hellohellohello // 動態鏈接var funcs = [foo, foo, foo];var result = Q('hello'); funcs.forEach(function (func) {  result = result.then(func);}); // 精簡后的動態鏈接funcs.reduce(function (prev, current) {  return prev.then(current);}, Q('hello'));

對于 promise 鏈,最重要的是需要理解為什么這個鏈能夠順序執行。如果能夠理解這點,那么以后自己寫 promise 鏈可以說是輕車熟路啊

promise 組合

回到我們一開始讀取文件內容的例子。如果現在讓我們把它改寫成 promise 鏈,是不是很簡單呢?

var Q = require('q'),  fs = require('fs'); function printFileContent(fileName) {  return function () {    var defer = Q.defer();    fs.readFile(fileName, 'utf8', function (err, data) {      if (!err && data) {        console.log(data);        defer.resolve();      }    })    return defer.promise;  }} // 手動鏈接printFileContent('sample01.txt')()  .then(printFileContent('sample02.txt'))  .then(printFileContent('sample03.txt'))  .then(printFileContent('sample04.txt'));  // 控制臺順序打印 sample01 到 sample04 的內容

很有成就感是不是。然而如果仔細分析,我們會發現為什么要他們順序執行呢,如果他們能夠并行執行不是更好嗎? 我們只需要在他們都執行完成之后,得到他們的執行結果就可以了

我們可以通過 Q.all([promise1,promise2...]) 將多個 promise 組合成一個 promise 返回。 注意:

1. 當 all 里面所有的 promise 都 fulfil 時,Q.all 返回的 promise 狀態變成 fulfil

2. 當任意一個 promise 被 reject 時,Q.all 返回的 promise 狀態立即變成 reject

我們來把上面讀取文件內容的例子改成并行執行吧

var Q = require('q');var fs = require('fs');/** *讀取文件內容 *@private */function printFileContent(fileName) {  // Todo: 這段代碼不夠簡潔??梢允褂?Q.denodeify 來簡化  var defer = Q.defer();   fs.readFile(fileName, 'utf8', function (err, data) {    if (!err && data) {      console.log(data);      defer.resolve(fileName + ' success ');    } else {      defer.reject(fileName + ' fail ');    }  })   return defer.promise; } Q.all([printFileContent('sample01.txt'), printFileContent('sample02.txt'), printFileContent('sample03.txt'), printFileContent('sample04.txt')])  .then(function (success) {    console.log(success);  }); // 控制臺打印各個文件內容 順序不一定

現在知道 Q.all 會在任意一個 promise 進入 reject 狀態后立即進入 reject 狀態。如果我們需要等到所有的 promise 都發生狀態后(有的 fulfil, 有的 reject),再轉換 Q.all 的狀態, 這時我們可以使用 Q.allSettled

var Q = require('q'),  fs = require('fs');/** *讀取文件內容 *@private */ function printFileContent(fileName) {   // Todo: 這段代碼不夠簡潔??梢允褂肣.denodeify來簡化  var defer = Q.defer();   fs.readFile(fileName, 'utf8', function (err, data) {    if (!err && data) {      console.log(data);      defer.resolve(fileName + ' success ');    } else {      defer.reject(fileName + ' fail ');    }  })   return defer.promise;   } Q.allSettled([printFileContent('nosuchfile.txt'), printFileContent('sample02.txt'), printFileContent('sample03.txt'), printFileContent('sample04.txt')])  .then(function (results) {    results.forEach(      function (result) {        console.log(result.state);      }    );  });

結束 promise 鏈

通常,對于一個 promise 鏈,有兩種結束的方式。第一種方式是返回最后一個 promise

如 return foo().then(bar);

第二種方式就是通過 done 來結束 promise 鏈

如 foo().then(bar).done()

為什么需要通過 done 來結束一個 promise 鏈呢? 如果在我們的鏈中有錯誤沒有被處理,那么在一個正確結束的 promise 鏈中,這個沒被處理的錯誤會通過異常拋出

var Q = require('q'); function getPromise(msg, timeout, opt) {   var defer = Q.defer();   setTimeout(function () {    console.log(msg);    if (opt)      defer.reject(msg);    else      defer.resolve(msg);  }, timeout);   return defer.promise; } /** * 沒有用 done() 結束的 promise 鏈 * 由于 getPromse('2',2000,'opt') 返回 rejected, getPromise('3',1000) 就沒有執行 * 然后這個異常并沒有任何提醒,是一個潛在的 bug */getPromise('1', 3000)  .then(function () { return getPromise('2', 2000, 'opt') })  .then(function () { return getPromise('3', 1000) }); /** * 用 done() 結束的 promise 鏈 * 有異常拋出 */getPromise('1', 3000)  .then(function () { return getPromise('2', 2000, 'opt') })  .then(function () { return getPromise('3', 1000) })  .done();

附錄:一個 Promise 簡單的應用(Node.js筆記(5)promise)

附:Promises/A+ 規范

promise 代表一個異步操作的最終結果。主要通過 promise 的 then 方法訂閱其最終結果的處理回調函數,和訂閱因某原因無法成功獲取最終結果的處理回調函數。

更對詳細見:Promises/A+

A 與 A+ 的不同點

  1. A+ 規范通過術語 thenable 來區分 promise 對象
  2. A+ 定義 onFulfilled/onRejectd 必須是作為函數來調用,而且調用過程必須是異步的
  3. A+ 嚴格定義了 then 方法鏈式調用時,onFulfilled/onRejectd 的調用順序

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情在线狂野欧美精品| 欧美在线视频在线播放完整版免费观看| 777777777亚洲妇女| 国产大片精品免费永久看nba| 国语自产精品视频在线看| 亚洲电影av在线| 欧美日韩国产页| 午夜精品久久久久久久99热| 亚洲欧美国产一区二区三区| 一本一本久久a久久精品综合小说| 久热在线中文字幕色999舞| 久久夜精品va视频免费观看| 久久免费观看视频| 国产精品视频久久| 日本道色综合久久影院| 国产精品一区二区女厕厕| 久久频这里精品99香蕉| 国产精品入口尤物| 最近2019年中文视频免费在线观看| 中文字幕国产精品久久| 欧美精品在线观看| 欧美性jizz18性欧美| 在线免费观看羞羞视频一区二区| 欧美性受xxxx黑人猛交| 国产高清视频一区三区| 人妖精品videosex性欧美| 亚洲美女精品成人在线视频| 96sao精品视频在线观看| 国产午夜精品全部视频播放| 国产精品一区二区三区久久| 精品亚洲男同gayvideo网站| 亚洲黄色www| 国产精品无码专区在线观看| 亚洲欧美成人一区二区在线电影| 亚洲成人精品视频| 国产精品精品久久久| 91精品国产自产在线观看永久| 日韩在线观看网站| 日韩av在线免费观看| 91精品国产综合久久香蕉的用户体验| 精品亚洲一区二区三区| 在线免费看av不卡| 色妞欧美日韩在线| 日韩在线观看免费高清| 国产精品h片在线播放| 精品久久久久久久久中文字幕| 久久青草福利网站| 91午夜在线播放| 久久久女女女女999久久| 久久影院资源网| 国产精品日本精品| 情事1991在线| 美女999久久久精品视频| 亚洲小视频在线| 欧美激情在线观看视频| 亚洲一区二区三区xxx视频| 亚洲精品中文字幕女同| 日韩中文字幕久久| 午夜精品久久久久久久99热浪潮| 亚洲人成电影网| 成人美女免费网站视频| 亚洲午夜精品久久久久久久久久久久| 91精品国产综合久久久久久蜜臀| 免费91在线视频| 亚洲综合在线中文字幕| 色播久久人人爽人人爽人人片视av| 久久免费视频网| 欧美精品午夜视频| 日韩欧美中文字幕在线观看| 少妇精69xxtheporn| 日韩中文在线中文网三级| 欧美精品在线看| 伦伦影院午夜日韩欧美限制| 国产精品日韩av| 欧美插天视频在线播放| 成人妇女淫片aaaa视频| 日韩欧美高清在线视频| 深夜福利一区二区| 欧美日韩在线第一页| 一区二区三欧美| 欧美午夜影院在线视频| 亚洲香蕉成视频在线观看| 国产精品网红福利| 午夜精品久久久久久99热| 在线电影av不卡网址| 欧美精品久久一区二区| 亚洲视频在线视频| 亚洲香蕉成人av网站在线观看| 91在线观看免费高清| 97成人精品视频在线观看| 精品久久在线播放| 亚洲精品福利视频| 国产精品白丝jk喷水视频一区| 精品视频中文字幕| 欧美电影院免费观看| 欧美肥老妇视频| 欧美黑人视频一区| 日本成人在线视频网址| 欧美超级乱淫片喷水| 国产欧美日韩丝袜精品一区| 日韩中文字幕网| 九九热视频这里只有精品| 欧美国产极速在线| 亚洲国产97在线精品一区| 91精品久久久久久久久久久久久久| 亚洲欧美国产高清va在线播| 亚洲欧美在线第一页| 国产精品久久久久国产a级| 欧美午夜女人视频在线| 欧美成人黄色小视频| 欧美区在线播放| 欧美日韩国产精品一区| 亚洲电影成人av99爱色| 2020国产精品视频| 国产丝袜视频一区| 57pao成人国产永久免费| www.日韩.com| 国产日韩av在线| 国产黑人绿帽在线第一区| 欧美另类老女人| 91在线高清视频| 永久免费看mv网站入口亚洲| 国产精品毛片a∨一区二区三区|国| 日韩精品在线观看一区二区| 久久久久久久久久久免费精品| 91精品国产综合久久久久久久久| 国产精品久久久久国产a级| 国产精品久久久一区| 亚洲自拍偷拍在线| 亚洲国产精品成人va在线观看| 国产亚洲成av人片在线观看桃| 日韩精品在线电影| 午夜精品视频在线| 国产91色在线| 日韩美女视频免费在线观看| 国产主播精品在线| 亚洲激情在线观看| 第一福利永久视频精品| 亚洲日韩欧美视频一区| 亚洲免费成人av电影| 久久久久国产视频| 57pao国产成人免费| 久久精品视频在线| 日本a级片电影一区二区| 成人网中文字幕| 91久久综合亚洲鲁鲁五月天| 欧美成人sm免费视频| 亚洲午夜精品久久久久久性色| 奇门遁甲1982国语版免费观看高清| 国产激情久久久久| 美女福利视频一区| 久久久女人电视剧免费播放下载| 欧美精品激情blacked18| 日韩av黄色在线观看| 在线观看久久久久久| 久久影视三级福利片| 欧美伦理91i| 2020国产精品视频| 亚洲人成在线观看网站高清| 久99九色视频在线观看| 欧美国产日韩一区二区在线观看| 欧美日韩裸体免费视频| 亚洲最大福利网| 7777免费精品视频|