1. 程式人生 > 實用技巧 >JavaScript--Promise(1)

JavaScript--Promise(1)

相信凡是寫過javascript的童鞋也一定都寫過回撥方法(callback),簡單說回撥方法就是將一個方法func2作為引數傳入另一個方法func1中,當func1執行到某一步或者滿足某種條件的時候才執行傳入的引數func2,例如下面的程式碼段
// 當引數a大於10且引數func2是一個方法時 執行func2
function func1(a, func2) {
    if (a > 10 && typeof func2 == 'function') {
        func2()
    }
}

func1(11, function() {
    console.log(
'this is a callback') })
一般來說我們會碰到的回撥巢狀都不會很多,一般就一到兩級,但是某些情況下,回撥巢狀很多時,程式碼就會非常繁瑣,會給我們的程式設計帶來很多的麻煩,這種情況俗稱——回撥地獄。 由此,Promise的概念就由社群提出並實現,作用與回撥方法幾乎一致,都是在某種情況下執行預先設定好的方法,卻能夠讓程式碼變得更簡潔清晰 一、什麼是Promise Promise是非同步程式設計的一種解決方案,它有三種狀態,分別是pending-進行中、resolved-已完成、rejected-已失敗 當Promise的狀態又pending轉變為resolved或rejected時,會執行相應的方法,並且狀態一旦改變,就無法再次改變狀態,這也是它名字promise-承諾的由來
二、ES6之前的Promise 在ES6中,Promise終於成為了原生物件,可以直接使用。但是在這之前,小夥伴們想要使用Promise,一般會藉助於第三方庫,或者當你知道其中的原理以後,也可以手動實現一個簡易的Promise 三、Promise的基本用法 1.宣告一個Promise物件
// 方法1
let promise = new Promise ( (resolve, reject) => {
    if ( success ) {
        resolve(a) // pending ——> resolved 引數將傳遞給對應的回撥方法
    } else {
        reject(err) 
// pending ——> rejectd } } ) // 方法2 function promise () { return new Promise ( function (resolve, reject) { if ( success ) { resolve(a) } else { reject(err) } } ) }
注意:例項化的Promise物件會立即執行 2.Promise.prototype.then() VS Promise.prototype.catch() .then()方法是Promise原型鏈上的方法,它包含兩個引數方法,分別是已成功resolved的回撥和已失敗rejected的回撥
promise.then(
    () => { console.log('this is success callback') },
    () => { console.log('this is fail callback') }
)
.catch()的作用是捕獲Promise的錯誤,與then()的rejected回撥作用幾乎一致。但是由於Promise的拋錯具有冒泡性質,能夠不斷傳遞,這樣就能夠在下一個catch()中統一處理這些錯誤。同時catch()也能夠捕獲then()中丟擲的錯誤,所以建議不要使用then()的rejected回撥,而是統一使用catch()來處理錯誤
promise.then(
    () => { console.log('this is success callback') }
).catch(
    (err) => { console.log(err) }
)
同樣,catch()中也可以丟擲錯誤,由於丟擲的錯誤會在下一個catch中被捕獲處理,因此可以再新增catch() 使用rejects()方法改變狀態和丟擲錯誤 throw new Error() 的作用是相同的 當狀態已經改變為resolved後,即使丟擲錯誤,也不會觸發then()的錯誤回撥或者catch()方法 then() 和 catch() 都會返回一個新的Promise物件,可以鏈式呼叫
promise.then(
    () => { console.log('this is success callback') }
).catch(
    (err) => { console.log(err) }
).then(
    ...
).catch(
    ...
)

3.Promise例項的非同步方法和then()中返回promise有什麼區別?

// p1非同步方法中返回p2
let p1 = new Promise ( (resolve, reject) => {
    resolve(p2)
} )
let p2 = new Promise ( ... )

// then()中返回promise
let p3 = new Promise ( (resolve, reject) => {
    resolve()
} )
let p4 = new Promise ( ... )
p3.then(
    () => return p4
)
p1非同步方法中返回p2 p1的狀態取決於p2,如果p2為pending,p1將等待p2狀態的改變,p2的狀態一旦改變,p1將會立即執行自己對應的回撥,即then()中的方法針對的依然是p1 then()中返回promise 由於then()本身就會返回一個新的promise,所以後一個then()針對的永遠是一個新的promise,但是像上面程式碼中我們自己手動返回p4,那麼我們就可以在返回的promise中再次通過 resolve() 和 reject() 來改變狀態 四.Promise的其他api 1.Promise.resolve() / Promise.reject() 用來包裝一個現有物件,將其轉變為Promise物件,但Promise.resolve()會根據引數情況返回不同的Promise: 引數是Promise:原樣返回 引數帶有then方法:轉換為Promise後立即執行then方法 引數不帶then方法、不是物件或沒有引數:返回resolved狀態的Promise Promise.reject()會直接返回rejected狀態的Promise 2.Promise.all() 引數為Promise物件陣列,如果有不是Promise的物件,將會先通過上面的Promise.resolve()方法轉換
var promise = Promise.all( [p1, p2, p3] )
promise.then(
    ...
).catch(
    ...
)
當p1、p2、p3的狀態都變成resolved時,promise才會變成resolved,並呼叫then()的已完成回撥,但只要有一個變成rejected狀態,promise就會立刻變成rejected狀態 3.Promise.race()
var promise = Promise.race( [p1, p2, p3] )
promise.then(
    ...
).catch(
    ...
)
“競速”方法,引數與Promise.all()相同,不同的是,引數中的p1、p2、p3只要有一個改變狀態,promise就會立刻變成相同的狀態並執行對於的回撥 4.Promise.done() / Promise. finally() Promise.done() 的用法類似 .then() ,可以提供resolved和rejected方法,也可以不提供任何引數,它的主要作用是在回撥鏈的尾端捕捉前面沒有被 .catch() 捕捉到的錯誤 Promise. finally() 接受一個方法作為引數,這個方法不管promise最終的狀態是怎樣,都一定會被執行