日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

十二、Promise的学习笔记(Promise的基本使用、链式编程、all())

發布時間:2024/7/5 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 十二、Promise的学习笔记(Promise的基本使用、链式编程、all()) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、認識Promise

ES6中一個非常重要和好用的特性就是Promise

  • 但是初次接觸Promise會一臉懵逼,這TM是什么東西?
  • 看看官方或者一些文章對它的介紹和用法,也是一頭霧水。

Promise到底是做什么的呢?

  • Promise是異步編程的一種解決方案。

那什么時候我們會來處理異步事件呢?

  • 一種很常見的場景應該就是網絡請求了。
  • 我們封裝一個網絡請求的函數,因為不能立即拿到結果,所以不能像簡單的3+4=7一樣將結果返回。
  • 所以往往我們會傳入另外一個函數,在數據請求成功時,將數據通過傳入的函數回調出去。
  • 如果只是一個簡單的網絡請求,那么這種方案不會給我們帶來很大的麻煩。

但是,當網絡請求非常復雜時,就會出現回調地獄。
OK,我以一個非??鋸埖陌咐齺碚f明。
我們來考慮下面的場景(有夸張的成分):

  • 我們需要通過一個url1從服務器加載一個數據data1,data1中包含了下一個請求的url2
  • 我們需要通過data1取出url2,從服務器加載數據data2,data2中包含了下一個請求的url3
  • 我們需要通過data2取出url3,從服務器加載數據data3,data3中包含了下一個請求的url4
  • 發送網絡請求url4,獲取最終的數據data4


上面的代碼有什么問題嗎?

  • 正常情況下,不會有什么問題,可以正常運行并且獲取我們想要的結果。
  • 但是,這樣額代碼難看而且不容易維護。

我們更加期望的是一種更加優雅的方式來進行這種異步操作。
如何做呢?

  • 就是使用Promise。
  • Promise可以以一種非常優雅的方式來解決這個問題。

二、Promise的基本使用

2.1 定時器的異步事件

我們先來看看Promise最基本的語法。

這里,我們用一個定時器來模擬異步事件:

  • 假設下面的data是從網絡上1秒后請求的數據
  • console.log就是我們的處理方式。

上圖是我們過去的處理方式,我們將它換成Promise代碼:

這個例子會讓我們感覺脫褲放屁,多此一舉

  • 首先,下面的Promise代碼明顯比上面的代碼看起來還要復雜。
  • 其次,下面的Promise代碼中包含的resolve、reject、then、catch都是些什么東西?

我們先不管第一個復雜度的問題,因為這樣的一個屁大點的程序根本看不出來Promise真正的作用。

2.2 定時器異步事件解析

我們先來認認真真的讀一讀這個程序到底做了什么?

  • new Promise很明顯是創建一個Promise對象
  • 小括號中((resolve, reject) => {})也很明顯就是一個函數,而且我們這里用的是之前剛剛學習過的箭頭函數。

但是resolve, reject它們是什么呢?

  • 我們先知道一個事實:在創建Promise時,傳入的這個箭頭函數是固定的(一般我們都會這樣寫)
  • resolve和reject它們兩個也是函數,通常情況下,我們會根據請求數據的成功和失敗來決定調用哪一個。

成功還是失敗?

  • 如果是成功的,那么通常我們會調用resolve(messsage),這個時候,我們后續的then會被回調。
  • 如果是失敗的,那么通常我們會調用reject(error),這個時候,我們后續的catch會被回調。

OK,這就是Promise最基本的使用了。

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body><script>// 1.使用setTimeout// setTimeout(() => {// console.log('Hello world!');// }, 1000)// new Promise(參數) 參數->函數(resolve,reject)// resolve,reject它們本身又是函數// 鏈式編程/*new Promise((resolve,reject) => {// 第一次發生網絡請求的代碼setTimeout(() => {// console.log('Hello world!');resolve()}, 1000)}).then(() => {// 第一次拿到結果后的處理代碼console.log('Hello world!');console.log('Hello world!');return new Promise((resolve, reject) => {// 第二次發生網絡請求的代碼setTimeout(() => {resolve()}, 1000)}).then(() => {// 第二次拿到結果后的處理代碼console.log('Hello vuejs!');console.log('Hello vuejs!');return new Promise((resolve, reject) => {// 第三次發生網絡請求的代碼setTimeout(() => {resolve()}, 1000)}).then(() => {// 第三次拿到結果后的處理代碼console.log('Hello promise!');console.log('Hello promise!');})})})*/// 什么情況下會用到Promise?// 一般情況下是有異步操作時,會使用Promise對這個異步操作進行封裝new Promise((resolve, reject) => {setTimeout(() => {// 成功的時候調用resolve// resolve('hello data')// 失敗的時候調用rejectreject('error message')}, 1000)}).then((data) => {console.log(data);console.log(data);console.log(data);console.log(data);}).catch((err) => {console.log(err);})</script> </body> </html>
  • then()處理成功,catch()處理失敗:

  • 不寫catch(),把處理成功和失敗的兩個函數都作為then()函數的參數傳進去:

  • 三、Promise三種狀態

    首先, 當我們開發中有異步操作時, 就可以給異步操作包裝一個Promise

    異步操作之后會有三種狀態,我們一起來看一下這三種狀態:

  • pending:等待狀態,比如正在進行網絡請求,或者定時器沒有到時間。
  • fulfill:滿足狀態,當我們主動回調了resolve時,就處于該狀態,并且會回調.then()
  • reject:拒絕狀態,當我們主動回調了reject時,就處于該狀態,并且會回調.catch()
  • 四、Promise的鏈式編程

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <script>// 1.使用setTimeout// setTimeout(() => {// console.log('Hello world!');// }, 1000)// new Promise(參數) 參數->函數(resolve,reject)// resolve,reject它們本身又是函數// 鏈式編程new Promise((resolve,reject) => {// 第一次發生網絡請求的代碼setTimeout(() => {// console.log('Hello world!');resolve()}, 1000)}).then(() => {// 第一次拿到結果后的處理代碼console.log('Hello world!');console.log('Hello world!');return new Promise((resolve, reject) => {// 第二次發生網絡請求的代碼setTimeout(() => {resolve()}, 1000)}).then(() => {// 第二次拿到結果后的處理代碼console.log('Hello vuejs!');console.log('Hello vuejs!');return new Promise((resolve, reject) => {// 第三次發生網絡請求的代碼setTimeout(() => {resolve()}, 1000)}).then(() => {// 第三次拿到結果后的處理代碼console.log('Hello promise!');console.log('Hello promise!');})})}) </script> </body> </html> <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body><script>// 網絡請求: aaa -> 處理代碼(10行代碼)// 處理:aaa111 -> 處理代碼(10行代碼)// 處理:aaa111222 -> 處理代碼(10行代碼)// new Promise((resolve, reject) => {})/* new Promise((resolve, reject) => {setTimeout(() => {resolve('aaa')}, 1000)}).then(res => {// 1.自己處理10行代碼console.log(res, '第一層的10行處理代碼')// 2.對結果進行第一次處理return new Promise((resolve, reject) => {resolve(res + '111')})}).then(res => {console.log(res, '第二層的10處理代碼');return new Promise((resolve, reject) => {resolve(res + '222')})}).then(res => {console.log(res, '第三層的10處理代碼');})*/// 2.// new Promise((resolve, reject) => {// setTimeout(() => {// resolve('aaa')// }, 1000)// }).then(res => {// // 1.自己處理10行代碼// console.log(res,'第一層的10行處理代碼')//// // 2.對結果進行第一次處理// // return new Promise((resolve, reject) => {// // resolve(res + '111')// // })// return Promise.resolve(res + '111')// }).then(res => {// console.log(res, '第二層的10處理代碼');//// return Promise.resolve(res + '222')//// }).then(res => {// console.log(res, '第三層的10處理代碼');// })// 鏈式調用中間某一層出現reject的情況,會直接執行最后面的catch()// new Promise((resolve, reject) => {// setTimeout(() => {// resolve('aaa')// }, 1000)// }).then(res => {// // 1.自己處理10行代碼// console.log(res, '第一層的10行處理代碼')//// // 2.對結果進行第一次處理// // return new Promise((resolve, reject) => {// // resolve(res + '111')// // })// return Promise.reject('error message')// }).then(res => {// console.log(res, '第二層的10處理代碼');//// return Promise.resolve(res + '222')//// }).then(res => {// console.log(res, '第三層的10處理代碼');// }).catch(err => {// console.log(err);// })// thrownew Promise((resolve, reject) => {setTimeout(() => {resolve('aaa')}, 1000)}).then(res => {// 1.自己處理10行代碼console.log(res, '第一層的10行處理代碼')// 2.對結果進行第一次處理// return new Promise((resolve, reject) => {// resolve(res + '111')// })throw 'error message'}).then(res => {console.log(res, '第二層的10處理代碼');return Promise.resolve(res + '222')}).then(res => {console.log(res, '第三層的10處理代碼');}).catch(err => {console.log(err);})// 3.省略掉Promise.resolve// new Promise((resolve, reject) => {// setTimeout(() => {// resolve('aaa')// }, 1000)// }).then(res => {// // 1.自己處理10行代碼// console.log(res, '第一層的10行處理代碼')//// return res + '111'// }).then(res => {// console.log(res, '第二層的10處理代碼');//// return res + '222'//// }).then(res => {// console.log(res, '第三層的10處理代碼');// })</script> </body> </html>

    4.1 鏈式調用

    • 我們在看Promise的流程圖時,發現無論是then還是catch都可以返回一個Promise對象。

    • 所以,我們的代碼其實是可以進行鏈式調用的:

    • 這里我們直接通過Promise包裝了一下新的數據,將Promise對象返回了

  • Promise.resovle():將數據包裝成Promise對象,并且在內部回調resolve()函數
  • Promise.reject():將數據包裝成Promise對象,并且在內部回調reject()函數
  • 4.2 鏈式調用簡寫

    簡化版代碼:
    如果我們希望數據直接包裝成Promise.resolve,那么在then中可以直接返回數據

    • 注意下面的代碼中,我將return Promise.resovle(data)改成了return data,結果依然是一樣的

    4.3 all方法的使用

    當需要多個網絡請求都成功后才能進行下一步操作時,可以使用Promise的all方法:

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body><script>// Promise.all([// new Promise((resolve, reject) => {// $ajax({// url: 'url1',// success: function (data) {// resolve(data)// }// })// }),//// new Promise((resolve, reject) => {// $ajax({// url: 'url2',// success: function (data) {// resolve(data)// }// })// })Promise.all([new Promise((resolve, reject) => {setTimeout(() => {resolve('result1')},2000)}),new Promise((resolve, reject) => {setTimeout(() => {resolve('result2')},1000)})]).then(results => {console.log(results);})</script> </body> </html>

    總結

    以上是生活随笔為你收集整理的十二、Promise的学习笔记(Promise的基本使用、链式编程、all())的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。