ES6-10:Promise

前端開發由於網絡交互的存在,產生了一種最多見的獨特場景——異步,即程序執行的過程並不是徹底按照代碼的書寫順序執行。異步編程的解決方法有①回調函數、②事件、③Promise、④觀察者對象;
Promise是ES6提供的一種異步編程的一種解決方案。簡單來書就是一個容器,裏面存放着某個將來纔會結束的事件;從語法角度來講是一個構造函數(對象),能夠對各類異步操做進行一樣的處理方法。前端

1.Promise特色

  • 3種狀態:Pending(進行中)、Fulfilled(已成功)、Rejected(已失敗);
  • 對象狀態不受外界影響:只有異步操做的結果能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態;
  • 2種不可逆狀態改變:只有兩種狀態改變①Pending->Fulffiled、②Pending->Rejected;只要兩種狀況發生任何一種,狀態就凝固定型再也不改變,即Resolved,任什麼時候候都能且僅能獲得這個結果;即便在添加新的對象也當即獲得Resolved的結果;

2. 建立方法

  • 建立:let p=new Promise(function(resolved,reject){});
var promise=new Promise(function(resolve,rejecte){
//do somthing here
if(/*異步操做成功*/){resolve(value)
}else{reject(value)};
})

// 案例1 :Promise建立時當即執行
let promise1=new Promise(function(resolve,reject){
    console.log("Promise is creating...");
    resolve();
});
promise1.then(function(){console.log("Promise is resolved !")});
console.log("Hi Script is Running...");


// Promise is creating...
// Hi Script is Running...
// Promise is resolved !

// 案例2:Promise返回值可帶參數
var p1=new Promise(function(resolve,reject){});
var p2=new Promise(function(resolve,reject){
    // do some other things...
    resolve(p1);
})

// 案例3 :Promise狀態定型的會回調函數在本輪事件循環結束時執行
new Promise((resolve,reject)=>{
    console.log(1);
    resolve(2);
    console.log(3);
}).then(res=>{
    console.log(res);
})
// 1
// 3
// 2

// 案例4:顯示return語句後的代碼不執行
new Promise(function(resolve,reject){
    console.log(1);
    return resolve(2);
    console.log(3);
}).then(res=>{
    console.log(res)
});
console.log(4)
// 1
// 4
// 2

Promise構造函數接受一個函數做爲參數,參數函數提供兩個參數方法,分別是resolve和reject,這兩個方法有JavaScript引擎提供,不用本身部署;Promise實例建立後會當即執行,而後會執行代碼中全部的同步操做, 最後會在Promise狀態定型後,執行then方法指定的回調函數 ;Promise的回調函數resolve和reject均可帶有參數;Promise的回調函數在狀態定性後的下一輪事件中執行,即不管狀態在何處定型(resolve()),都不影響Promise中其餘代碼的執行,但顯示return語句會影響;編程

3. 基本方法

  • Promise.prototype.then(resolveFn,rejectFn?):爲Promise實例添加狀態改變是的回調函數,返回至爲Promise對象;該方法可鏈式重複調用,將前一個處理結果做爲下一個函數的入參,如:promise.then().then()
  • Promise.prototype.catch():指定Promise發生錯誤時的回調函數,返回值爲Promise對象,即Promise.then(null,rejection)的別名;Promise的錯誤對象具備「冒泡」性質,會一直向後傳遞,直到被catch或reject捕獲;但若是Promise沒有使用catch指定錯誤的處理方法,Promise的錯誤方法將永遠不會傳遞到外層代碼,即不會有任何反應;
// 案例5:Promise 錯誤對象冒泡--then過程當中的錯誤會一直傳遞給最後至被捕獲
let p1=new Promise((resolve,reject)=>{resolve(httpFn)});
let p2=new Promise((resolve,reject)=>{p1});
let p3=new Promise((resolve,reject)=>{});
p3.then(p2).then(otherFn).catch(err=>{errorFn});

// 案例6:Promise的狀態一旦定性將沒法被改變,即一個Promise實例有且僅有一次改變狀態的機會
let p4=new Promise((resolve,reject)=>{
    resolve('ok');
    throw new Error('test');
});
p4.then(res=>{console.log(res)}).catch(err=>{console.log(err)});
// ok

// 案例7
let soneFn=function(){
    return new Promise(function(resolve,reject){
        resolve(x+2);//此處應該報錯,由於x未聲名 
    })
}
someFn.then(function(){console.log('Everythings is ok.')});
// Everything is ok.
/////因未使用catch捕獲Promise異常,報錯不會被捕獲,也不會傳遞到外層代碼;相反代碼正常運行,但會打印錯誤ReferenceError: x is not defined.
  • Promise.all(arrLike):將一個具備Iterator接口的數據對象包裝成一個新的Promise實例,返回值;

①參數arrLike能夠是Promise數組、或具備遍歷器的數據;若是參數不是Promise數組,則調用Promise.resolve()方法將參數轉爲Promise實例,在進一步處理;數組

②返回Promise實例的狀態:被封裝的Promise實例都爲Fullfiled狀態時,封裝返回Promise狀態纔會變成Fullfied;不然只要有一個爲rejected,則會將第一個rejected的實例返回給封裝後的Promise,同時,封裝後的Promise都會變成rejected;promise

let pro1=new Promise.all([p1,p2,p3]);
let pro2=new Promise.all([1,2,3]);
  • Promise.race(arrLike):將多個具備Iterator接口的數據包裝成一個Promise實例;與Promise.all()方法相似;不一樣之處在於,只要被包裝的Promise實例只要有一個率先改變狀態,變回將狀態結果傳遞給封裝後的Promise對象;
  • Promise.resolve(argu):將一個數據轉換成Promise對象;根據傳入參數類型的不一樣處理方法不一樣,以下:
    ① 參數不存在:直接返回一個狀態爲Resolved的Promise對象;
    ② Promise對象:返回Promise對象,不作任何處理;
    thenable對象:即一個具備then方法的對象;將這個對象轉換成Promise對象並當即執行htneable的then方法;
    ④ 不具備thenable方法或非對象:返回一個新的Promise對象,狀態爲resolved,結果爲參數自己;
  • Promise.reject(argu):返回一個Promise對象,其狀態爲Rejected;錯誤結果爲整個參數自己;

5. 與steam事件、Observerble(觀察者模式的區別)

  • Promise、Observe都是將異步操做轉換成同步操做的實現方式;
  • Promise、Observe均可以進行聚合操做;
  • Promise的狀態是不可逆 的,其狀態僅有一次改變的機會,一旦改變,狀態便定型;結果值須要手動調用纔可傳遞給後續操做
  • Observe的狀態是能夠屢次重複可變的,其狀態會根據入參改變並傳遞給觀察者;結果值會主動通知到全部訂閱者(後續操做);
相關文章
相關標籤/搜索