ES6中的Promise使用總結
One、什麼是Promise?
Promise是非同步程式設計的解決方案,而它本身也就是一個建構函式,比傳統的非同步解決【回撥函式】和【事件】更合理,更強大。
Two、Promise有何作用?
作用:解決回撥地獄
當我們在寫邏輯函式時,可能函式內部會有另一個函式,而我們在處理一些比較複雜的操作的時候,有可能裡面會巢狀十幾二十個函式都說不定,那麼看一下下面的程式碼:
1 //需求 : 非同步操作按照順序執行(非同步預設無序) 2 3 //需求: (1)先讀取a (2)然後讀取b (3)然後讀c (4)最後讀取d 4 5 6 const fs = require('fs'); 7 8 //下面出現了回撥地獄 9 //(1)讀取A 10 fs.readFile('./data/a.txt', 'utf8', (err, data) => { 11 if (err) { 12 throw err; 13 } else { 14 console.log(data); 15 //(2)讀取B 16 fs.readFile('./data/b.txt', 'utf8', (err, data) => { 17 if (err) { 18 throw err; 19 } else { 20 console.log(data); 21 //(3)讀取C 22 fs.readFile('./data/c.txt', 'utf8', (err, data) => { 23 if (err) { 24 throw err; 25 } else { 26 console.log(data); 27 //(4)讀取D 28 fs.readFile('./data/d.txt', 'utf8', (err, data) => { 29 if (err) { 30 throw err; 31 } else { 32 console.log(data); 33 } 34 }) 35 } 36 }) 37 } 38 }) 39 } 40 })
像這樣的程式碼維護起來非常麻煩,那麼如何使用Promise來解決?看下來:
Three、promise基本使用:
(1)例項化promise物件(將非同步放入promise容器) :
let p = new Promise((resolve,reject)=>{ 你的非同步操作 })
(2)呼叫promise例項的then方法 (處理非同步結果):
p.then(data=>{},err=>{})
再看一個根據上面優化的程式碼:
1 const fs = require('fs'); 2 3 //1.建立Promise例項化物件 (Promise是一個建構函式,作用是建立promise例項) 4 //引數是一個回撥函式 : (resolve, reject)=>{ 你的非同步操作 } 5 let p = new Promise((resolve,reject)=>{ 6 fs.readFile('./data/b.txt','utf8',(err,data)=>{ 7 if(!err){ 8 //成功 9 /* 10 1.成功就執行resolve() , 會呼叫then的第一個函式 11 */ 12 resolve(data); 13 }else{ 14 //失敗 15 /* 16 2.失敗就執行reject(),會呼叫then的第二個函式 17 */ 18 reject(err); 19 } 20 }); 21 }); 22 23 24 //2.呼叫promise例項的then方法 25 /* 26 第一個引數: 回撥函式 (data)=>{} 27 第二個引數: 回撥函式 (err)=>{} 28 */ 29 p.then(data=>{ 30 //成功 31 console.log(data); 32 33 },err=>{ 34 //失敗 35 console.log(err); 36 37 });
Four、Promise原理介紹 :
(1)promise有三種狀態
pending:進行中
fulfilled:已成功
rejected:已失敗
1-----只有非同步操作的結果,可以決定Promise是哪一種狀態,任何其他操作都無法改變這個狀態
2-----一旦Promise狀態改變,就不會再有變化,任何時候都可以得到這個結果。Promise物件的狀態改變,只有兩種可能:從pending變為fulfilled 或者 從pending變為rejected。只要這兩種情況發生,狀態就不會再變了,會一直保持這個結果,這時就稱為 resolved(已定型)。如果改變已經發生了,你再對Promise物件添加回調函式,也會立即得到這個結果。這與事件(Event)不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的
使用Promise的好處,就是在處理非同步程式時,將非同步操作佇列化,按照期望的順序執行,返回符合預期的結果,這樣即使是多重非同步操作,也可以方便的使用Promise進行鏈式呼叫
3-----Promise
也有一些缺點
首先,無法取消Promise
,一旦新建它就會立即執行,無法中途取消。其次,如果不設定回撥函式,Promise
內部丟擲的錯誤,不會反應到外部。第三,當處於pending
狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)
第二部分、循序漸進的介紹Promise的用法
(2)promise狀態改變只有兩種情況
從pending進行中變成fulfilled:已成功
從pending進行中變成rejected: 已失敗
(3)promise中的非同步函式在建立的時候會預設執行
* a. 非同步永遠都是無序的,這一點無法改變的
* b. promise沒有改變非同步的順序,而是改變非同步的結果
* c. 不要在建立promise的時候去操作非同步的結果,應該呼叫resolve在then方法種操作結果
(4)promise控制非同步操作順序的核心原理 : 在上一個promise的then方法中return下一個promise
1 const fs = require('fs'); 2 3 //需求: (1)先讀取a (2)然後讀取b (3)然後讀c (4)最後讀取d 4 5 //(1)例項化promise物件 6 let p1 = new Promise((resolve,reject)=>{ 7 //非同步操作 8 fs.readFile('./data/a.txt','utf8',(err,data)=>{ 9 if(!err){//成功執行的操作 10 /* 11 (1)resolve() 呼叫then的第一個函式 12 (2)作用: 改變promise的狀態 從 從pending進行中變成fulfilled:已成功 13 */ 14 resolve(data); 15 16 }else{ 17 /* 18 (1)resolve() 呼叫then的第二個函式 19 (2)作用: 從pending進行中變成rejected: 已失敗 20 */ 21 reject(err); 22 }; 23 }); 24 }); 25 26 let p2 = new Promise((resolve,reject)=>{ 27 //非同步操作 28 fs.readFile('./data/b.txt','utf8',(err,data)=>{ 29 if(!err){//成功執行的操作 30 resolve(data); 31 }else{ 32 reject(err); 33 }; 34 }); 35 }); 36 37 let p3 = new Promise((resolve,reject)=>{ 38 //非同步操作 39 fs.readFile('./data/c.txt','utf8',(err,data)=>{ 40 if(!err){//成功執行的操作 41 resolve(data); 42 }else{ 43 reject(err); 44 }; 45 }); 46 }); 47 48 //(2)呼叫promise例項的then方法 49 50 p1.then(data=>{ 51 console.log(data); //這是p1的資料 52 return p2;//在p1的then方法中返回p2 53 }) 54 .then(data=>{//呼叫p2的then方法 55 console.log(data); //這是p2的資料 56 return p3; 57 }) 58 .then(data=>{//呼叫p3的then方法 59 console.log(data); //這是p3的資料 60 });View Code
精闢個人總結:promise控制非同步順序的本質 不是控制非同步操作的本身 ,而是控制非同步操作的結果
Five、Promise的catch方法的使用:
catch作用: 捕捉promise的異常
1 const fs = require('fs'); 2 3 //需求: (1)先讀取a (2)然後讀取b (3)然後讀c (4)最後讀取d 4 5 function getPromise(fileName) { 6 return new Promise((resolve, reject) => { 7 //非同步操作 8 fs.readFile(`./data/${fileName}.txt`, 'utf8', (err, data) => { 9 if (!err) {//成功 10 resolve(data); 11 } else { 12 reject(err); 13 }; 14 }); 15 }); 16 } 17 18 /* catch作用: 捕捉promise的異常 */ 19 20 //(1)例項化promise物件 21 let p1 = getPromise('a'); 22 let p2 = getPromise('b'); 23 let p3 = getPromise('c'); 24 25 //(2)呼叫promise例項的then方法 26 p1.then(data=>{ 27 console.log(data); 28 return p2; 29 }).then(data=>{ 30 console.log(data); 31 return p3; 32 }).then(data=>{ 33 console.log(data); 34 }).catch(err=>{ 35 //上面所有的promise只要有任何一個出現錯誤,就會執行catch 36 console.log(err); 37 })View Code
Six、Promise的all方法的使用:
all作用 : 將多個promise合併成一個promise,所有的promise執行完畢才會走then方法 (&&)
1 const fs = require('fs'); 2 3 //需求: (1)先讀取a (2)然後讀取b (3)然後讀c (4)最後讀取d 4 5 function getPromise(fileName) { 6 return new Promise((resolve, reject) => { 7 //非同步操作 8 fs.readFile(`./data/${fileName}.txt`, 'utf8', (err, data) => { 9 if (!err) {//成功 10 resolve(data); 11 } else { 12 reject(err); 13 }; 14 }); 15 }); 16 } 17 18 /* 1.catch作用: 捕捉promise的異常 19 2.all作用 : 將多個promise合併成一個promise,所有的promise執行完畢才會走then方法 20 */ 21 22 //(1)例項化promise物件 23 let p1 = getPromise('a'); 24 let p2 = getPromise('b'); 25 let p3 = getPromise('c'); 26 27 //多個promise合併成一個promise 28 let pAll = Promise.all([p1,p2,p3]); 29 30 //(2)呼叫promise例項的then方法 31 pAll.then(data=>{ 32 //所有的promise都執行完畢,data是一個數組,儲存每一個promise的操作結果 33 console.log(data); 34 return p2; 35 }).catch(err=>{ 36 //上面所有的promise只要有任何一個出現錯誤,就會執行catch 37 console.log(err); 38 })View Code
Seven、Promise的race方法的使用:
race作用: 將多個promise合併成一個promise,任意primise執行完畢就會走then方法 (||)
1 //(1)例項化promise物件 2 let p1 = getPromise('/ada/dada'); 3 let p2 = getPromise('b'); 4 let p3 = getPromise('c'); 5 6 //多個promise合併成一個promise 7 let pAll = Promise.race([p1, p2, p3]); 8 9 //(2)呼叫promise例項的then方法 10 Promise.race([p1, p2, p3]).then(data => { 11 //任意promise執行完畢就會走then,此時其他的promise不再執行 12 console.log(data); 13 }, (err) => { 14 console.log('有檔案錯誤'); 15 })View Code
喜歡分享,喜歡學習,這些確實是在遇到的問題中解決問題的個人總結,如果喜歡,請點個贊,也歡迎到下方評論,我們一起探討技術......
個人github地址請移步-->
&n