1.1 回呼函數
回呼函數:把函數A當作參數傳遞給另一個函數B調用,那麼A就是回呼函數。 【推薦:JavaScript影片教學】
一些例子具名回調
function 你有幾隻狗(fn){ fn('一隻狗') }function 數狗(數量){ console.log(數量) } 你有幾隻狗(數狗) // 一隻狗
匿名回調
function 你有幾隻狗(fn){ fn('一隻狗') } 你有幾隻狗(function(數量){console.log(數量) }) // 一隻狗
常見的例子
jQuery中使用回呼函數,這裡用的是匿名回呼的方式
$("#btn").click(function(){ console.log('點到我了') })
1.2 回調地獄(回調缺點1)
回調地獄:指的是回呼嵌套過多的情況,導致程式碼很難被看懂。
let info = []function 你有幾隻狗(fn){ fn('一隻狗') }function 你有幾隻貓(fn){ fn('一隻貓') }function 知道了(數量,callback){ info.push(數量) console.log(info) if(callback){ callback() } }// 開始呼叫 如果比這再多幾層,就不容易看懂了你有幾隻狗(function(狗數){ console.log(狗數) 知道了(狗數, function(){ 你有幾隻貓(function(貓數){ console.log(貓數) 知道了(貓數) }) }) })
1.3 不使用Promise,如何解決
利用具名函數代替匿名函數
let info = []function 你有幾隻狗(fn){ fn('一隻狗') }function 你有幾隻貓(fn){ fn('一隻貓') }function 知道了(數量,callback){ info.push(數量) console.log(info) if(callback){ callback() } }function 告訴你貓的個數(貓數){ console.log(貓數) 知道了(貓數) }function 繼續數(){ 你有幾隻貓(告訴你貓的個數) }function 告訴你狗的個數(狗數){ console.log(狗數) 知道了(狗數, 繼續數) } 你有幾隻狗(告訴你狗的個數) // 好像也沒好到哪裡去。 。 。
1.4 回調方式各不相同,需單獨記憶(回調缺點2)
readFile('C:\1.txt',function (error, data) { // node.js 讀取檔案方法中的回呼 if(error) { console.log('成功') console.log(data.toString()) } else { console.log('讀取檔失敗') } }) $.ajax({ // jQuery中ajax方法中的回呼 url:'/2.txt' success: function(response) { console.log('成功') }, error: function(){ console.log('失敗') } })
Promise 是非同步程式設計的解決方案,比傳統的解決方案——回呼函數和事件——更合理和更強大。它由社群最早提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了Promise物件。
3.1 實現原理
ES6 規定,Promise物件是一個建構函數,用來產生Promise實例。透過在函數內部return 一個Promise物件的實例,這樣就可以使用Promise的屬性和方法進行下一步操作了。
function 函式名稱(){ return new Promise(function(resolve, reject) { // ... some code if (/* 非同步操作成功 */){ resolve(value); // 非同步操作成功時調用,把結果當作參數傳遞出去 } else { reject(error); // 非同步失敗時調用,把錯誤當作參數傳遞出去 } }) }
3.2 呼叫邏輯
S1和E1兩個都沒報錯,執行S2(resolve執行,系統認為搞定了,沒報錯)
S1和E1任何一個有報錯,執行E2(reject執行,系統認為沒搞定,報錯了)
前端(vue)入門到精通課程:進入學習
4.1 Promise 的屬性與方法
屬性
Promise.prototype 表示Promise 構造器的原型方法
Promise.prototype.then()
返回一個Promise 。它最多需要有兩個參數:Promise 的成功和失敗情況的回呼函數。
Promise.prototype.catch()
返回一個Promise,並且處理拒絕的情況。等價於Promise.prototype.then(undefined, onRejected)
Promise.prototype.finally()
finally() 方法傳回一個Promise,執行then()和catch()後,都會執行finally指定的回呼函數。避免同樣的語句需要在then()和catch()中各寫一次的情況。
Promise.all(iterable)
傳回一個Promise 實例,iterable參數內所有的promise 都resolved後,才回呼完成resolve。
Promise.race(iterable)
傳回一個promise ,並伴隨著promise物件解決的回傳值或拒絕的錯誤原因, 只要iterable 中有一個promise 物件」解決(resolve)」或」拒絕(reject)」。
Promise.resolve()
傳回一個以給定值解析後的Promise物件。但如果這個值是個thenable(即帶有then方法),回傳的promise會「跟隨」這個thenable的對象,採用它的最終狀態(指resolved/rejected/pending/settled);如果傳入的value本身就是promise對象,則該物件以Promise.resolve方法的返回值返回;否則以該值為成功狀態傳回promise物件。
Promise.reject()
傳回一個有拒絕原因reason參數的Promise物件。
4.2 將回調地獄中的例子,改寫為Promise的形式
可以看到使用Promise後,邏輯變得非常直覺寫得更完整一些
Promise套Promise時,也就是Promise鏈的時候-注意訊息的傳遞一個失敗的例子,當我們使用Promise鏈的時候,如果每一步都需要上一步驟的資料時,就需要傳參,成功透過resolve傳參,失敗透過reject傳參,如果忘記傳參,就得不到想要的結果。
resolve把成功的數據回傳給下一個回調
reject把失敗的資料回傳給下一個回呼。
給這裡的resolve傳一個參改成失敗的例子先不給reject傳參,如果失敗的話,下一個回調拿不到數據
給reject傳參
我們可以看到,即使是走的失敗回調,下一個成功回調還是執行了,由於不知道() 默認返回undefined, 相當於失敗已經處理了,在成功和失敗都被處理的情況下,下一個回調會執行的。
改成符合預期的,即失敗不呼叫。
失敗不調用的簡寫形式
上述情況執行後.then(除了狗呢)裡面的成功回調沒有執行,我們增加一個失敗回調看看
同樣也可以返回resolve,讓後面成功回調可以執行
4.3 應用
載入圖片將圖片的載入寫成一個Promise,一旦載入完成,Promise的狀態就會改變。
const preloadImage = function (path) { return new Promise(function (resolve, reject) { const image = new Image(); image.onload = resolve; image.onerror = reject; image.src = path; }); };
Generator 函數與Promise 的結合(詳情請參閱參考鏈接,阮一峰的教程)
5.1 await
成功的情況
失敗的情況利用try catch
await 配合try catch使用,比較完整
能利用Promise對象,把普通函數改成返回Promise的形式,解決回調地獄的問題。
明白Promise的成功失敗呼叫邏輯,可以靈活的進行調整。
理解核心知識,先用起來,慢慢整合吸收知識。
以上就是實例解析ES6 Promise的原理和使用的詳細內容!