Promise有哪幾種狀態,各個狀態之間是如何進行轉換的?


一、什么是Promise?

1.Promise的結構:

class Promise{
    constructor(exector){
        function resolve(){
            
        }
        function reject(){
            
        }
        exector(resolve,reject)    
    }
    then(){
        
    }
}

2.Promise的三種狀態:

pending、fulfilled、rejected(未決定,履行,拒絕),同一時間只能存在一種狀態,且狀態一旦改變就不能再變。promise是一個構造函數,promise對象代表一項有兩種可能結果(成功或失敗)的任務,它還持有多個回調,出現不同結果時分別發出相應回調。

1.初始化,狀態:pending

2.當調用resolve(成功),狀態:pengding=>fulfilled

3.當調用reject(失敗),狀態:pending=>rejected

const PENDING = "pending";//Promise會一直保持掛起狀態,知道被執行或拒絕。
const FULFULLED = "fulfilled";
const REJECTED = "rejected";
class Promise{
    constructor(exector){
        let self = this;//緩存當前promise對象
        self.status = PENDING;//初始狀態,對promise對象調用state(狀態)方法,可以查看其狀態是“pending"、"resolved"、還是”rejected“
        self.value = undefined;// fulfilled狀態時 返回的信息
        self.reason = undefined;// rejected狀態時 拒絕的原因
        self.onResolveCallBacks = [];// 存儲resolve(成功)狀態對應的onFulfilled函數
        self.onRejectCallBacks = [];// 存儲rejected(失敗)狀態對應的onRejected函數
        let resolve = (value) => {//成功
            if(self.status === PENDING){//如果成功則,狀態由pending=>fulfilled
                self.status = FULFULLED;
                self.value = value;
                self.onResolveCallBacks.forEach(cb=>cb(self.value));//執行發布
            }
        }
        let reject = (reason) => {//失敗
            if(self.status === PENDING){//如果失敗,則狀態由pending=>rejected
                self.status = REJECTED;
                self.reason = reason;
                self.onRejectCallBacks.forEach(cb=>cb(self.reason));//執行發布
            }
        }
        
        try{
            exector(resolve,reject)                 
        }catch(e){
            reject(e)
        }
    }
    then(onFulfilled,onRejected){
        let self=this;
        if(self.status === FULFULLED){
            onFulfilled(self.value);//成功值
        }
        if(self.status === REJECTED){
            onFulfilled(self.reason);//拒絕原因
        }
        if(self.status === PENDING){
            self.onResolveCallBacks.push(onFulfilled);//訂閱發布
            self.onRejectCallBacks.push(onRejected);//訂閱發布
        }
    }
    //promise的決議結果只有兩種可能:完成和拒絕,附帶一個可選的單個值。如果Promise完成,那么最終的值稱為完成值;如果拒絕,那么最終的值稱為原因。Promise只能被決議(完成或拒絕)一次。之后再次試圖完成或拒絕的動作都會被忽略。
}
new Promise((resolve,reject)=>{
    resolve("挖坑妹");
    //異步處理
    //處理結束后、調用resolve或reject
}).then((data)=>{
    console.log(data);//"挖坑妹"
},(reason)=>{
    console.log(reason);
})

3.promise的優缺點

​ 優點:

​ 1.Promise 分離了異步數據獲取和業務邏輯,有利於代碼復用。

​ 2.可以采用鏈式寫法

​ 3.一旦 Promise 的值確定為fulfilled 或者 rejected 后,不可改變。

​ 缺點:

​ 代碼冗余,語義不清。

 

二、為什么用Promise?

1.解決回調地獄

​ 回調地獄:發送多個異步請求時,每個請求之間相互都有關聯,會出現第一個請求成功后再做下一個請求的情況。我們這時候往往會用嵌套的方式來解決這種情況,但是這會形成”回調地獄“。如果處理的異步請求越多,那么回調嵌套的就越深。出現的問題:

1.代碼邏輯順序與執行順序不一致,不利於閱讀與維護。

2.異步操作順序變更時,需要大規模的代碼重構。

3.回調函數基本都是匿名函數,bug追蹤困難。

const request = url => {
    return new Promise((resolve,reject) => {
        $.get(url,params => {
            resolve(params)
        });
    });
};
​
request(url).then(params1 => {
    return request(params1.url);   
}).then(params2 => {
    return request(params2.url);
}).then(params3 => {
    console.log(params3);
}).catch(err => throw new Error(err));

2.解決異步

我們都知道js是單線程執行代碼,導致js的很多操作都是異步執行(ajax)的,以下是解決異步的幾種方式:

​ 1.回調函數(定時器)。

​ 2.事件監聽。

​ 3.發布/訂閱。

​ 4.Promise對象。(將執行代碼和處理結果分開)

​ 5.Generator。

​ 6.ES7的async/await。

三、怎么用Promise?

promise有幾種對象方法

1.then方法(異步執行)

當resolve(成功)/reject(失敗)的回調函數

//onFulfilled 是用來接收promise成功的值
//onRejected 是用來接收promise失敗的原因
promise.then(onFulfilled,onRejected)


2.resolve(成功)

​ 調用onFulfilled

const promise = new Promise((resolve,reject)=>{
   resolve('fulfilled');//狀態:pending=>fulfilled
});

promise.then(result =>{//onFulfilled調用
console.log(result);//'fulfilled'  
},result =>{//onRejected不調用
   
})

//注:resolve使用
Promise.resolve('hellow world')相當於
//相當於
const promise = new Promise(resolve=>{
   resolve('hellow world');
})
 

3.reject(失敗)

​ 調用onRejected

const promise = new Promise((resolve,reject)=>{
reject('rejected');//狀態:pending=>rejected    
});

promise.then(result =>{//onFulfilled不調用

},result =>{//onRejected調用
   console.log(result);//'rejected'  
})

//注:reject使用
Promise.reject('err')相當於
//相當於
const promise = new Promise((resolve,reject)=>{
   reject('err');
});


4.catch

​ 鏈式寫法中可以捕獲前面then中發送的異常,這種寫法的好處在於先執行promise操作,然后根據返回的結果(成功或失敗)來調用onFulfilled(或者onRrejected)函數。

promise.then(onFulfilled).catch(onRrejected); 

 

5.all

​ Promise.all接收一個promise對象數組為參數,處理並行異步操作會用到,但是需要全部為resolve才能調用。這種情況是幾個任務可以並行執行

const promise1= new Promise((resolve,reject)=>{
    resolve('promise1');
});
const promise2= new Promise((resolve,reject)=>{
    resolve('promise2');
});
const promise3= new Promise((resolve,reject)=>{
    resolve('promise3');
});
Promise.all([promise1, promise2, promise3]).then(data => { 
    console.log(data); 
    // ['promise1', 'promise2', 'promise3'] 結果順序和promise實例數組順序是一致的
}, err => {
    console.log(err);
});

可以從一個promise對象派生出新的promise對象,我們可以要求代表着並行任務的兩個promise對象合並成一個promise對象,由后者負責通知前面的那些任務都已完成。也可以要求代表着任務系列中首要任務的Promise對象派生出一個能代表任務系列中末任務的Promise對象,這樣后者就能知道這一系列的任務是否均已完成。

 

6.race

​ Promise.race接收一個promise對象數組為參數,只要有一個promise對象進入Fulfilled或者Rejected狀態的話,就會進行后面的處理。這可以解決多個異步任務的容錯

function racePromise(time){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(time);
        },time)
    })
}
var startDate = Date.now();
Promise.race([
    racePromise(5),
    racePromise(50),
    racePromise(500),
]).then(function(values){
    console.log(values);5
})

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM