JavaScript之實現一個簡單的promise

本文博客原文地址git

咱們在開發過程當中大多會用到promise,想必你們對promise的使用都很熟練了,今天咱們就來實現一個簡單的promise,實現的效果若有出入還往指正。es6

總體結構

咱們先來梳理一下總體的結果,以便後續好操做github

class MyPromise {
    constructor(fn){
        
    }
    resolve(){

    }
    then(){

    }
    reject(){

    }
    catch(){

    }
}

Promise理論知識

摘抄至 http://es6.ruanyifeng.com/#do...

Promise對象有如下兩個特色。promise

(1)對象的狀態不受外界影響。Promise對象表明一個異步操做,有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗)。只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。這也是Promise這個名字的由來,它的英語意思就是「承諾」,表示其餘手段沒法改變。異步

(2)一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果。Promise對象的狀態改變,只有兩種可能:從pending變爲fulfilled和從pending變爲rejected。只要這兩種狀況發生,狀態就凝固了,不會再變了,會一直保持這個結果,這時就稱爲 resolved(已定型)。若是改變已經發生了,你再對Promise對象添加回調函數,也會當即獲得這個結果。這與事件(Event)徹底不一樣,事件的特色是,若是你錯過了它,再去監聽,是得不到結果的。函數

總結一下就是promise有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗),還有就是狀態的改變只能是pending -> fulfilled 或者 pending -> rejected,這些很重要測試

實現構造函數

如今咱們開始實現構造函數this

class MyPromise {
    constructor(fn){
        if(typeof fn !== 'function') {
            throw new TypeError(`MyPromise fn ${fn} is not a function`)
        }
        this.state = 'pending';
        this.value = void 0;
        fn(this.resolve.bind(this),this.reject.bind(this))
    }
    ...
}

構造函數接收一個參數fn,且這個參數必須是一個函數,由於咱們通常這樣使用new Promise((resolve,reject)=>{});
而後初始化一下promise的狀態,默認開始爲pending,初始化value的值。
fn接收兩個參數,resolverejectdebug

resolve

class MyPromise {
    constructor(fn){
        if(typeof fn !== 'function') {
            throw new TypeError(`MyPromise fn ${fn} is not a function`)
        }
        this.state = 'pending';
        this.value = void 0;
        fn(this.resolve.bind(this),this.reject.bind(this))
    }
    resolve(value){
        if(this.state !== 'pending') return;
        this.state = 'fulfilled';
        this.value = value
    }
    ...
}

resolve執行,接收到一個值以後;狀態就由 pending -> fulfilled;當前的值爲接收的值code

reject

class MyPromise {
    constructor(fn){
        if(typeof fn !== 'function') {
            throw new TypeError(`MyPromise fn ${fn} is not a function`)
        }
        this.state = 'pending';
        this.value = void 0;
        fn(this.resolve.bind(this),this.reject.bind(this))
    }
    resolve(value){
        if(this.state !== 'pending') return;
        this.state = 'fulfilled';
        this.value = value
    }
    reject(reason){
        if(this.state !== 'pending') return;
        this.state = 'rejected';
        this.value = reason
    }
}

reject執行,接收到一個值以後;狀態就由 pending -> rejected;當前的值爲接收的值

then

class MyPromise {
    constructor(fn){
        if(typeof fn !== 'function') {
            throw new TypeError(`MyPromise fn ${fn} is not a function`)
        }
        this.state = 'pending';
        this.value = void 0;
        fn(this.resolve.bind(this),this.reject.bind(this))
    }
    resolve(value){
        if(this.state !== 'pending') return;
        this.state = 'fulfilled';
        this.value = value
    }
    reject(reason){
        if(this.state !== 'pending') return;
        this.state = 'rejected';
        this.value = reason
    }
    then(fulfilled,rejected){
        if (typeof fulfilled !== 'function' && typeof rejected !== 'function' ) {
            return this;
        }
        if (typeof fulfilled !== 'function' && this.state === 'fulfilled' ||
            typeof rejected !== 'function' && this.state === 'rejected') {
            return this;
        }
        return new MyPromise((resolve,reject)=>{
            if(fulfilled && typeof fulfilled === 'function' && this.state === 'fulfilled'){
                let result = fulfilled(this.value);
                if(result && typeof result.then === 'function'){
                    return result.then(resolve,reject)
                }else{
                    resolve(result)
                }
            }
            if(rejected && typeof rejected === 'function' && this.state === 'rejected'){
                let result = rejected(this.value);
                if(result && typeof result.then === 'function'){
                    return result.then(resolve,reject)
                }else{
                    resolve(result)
                }
            }
        })
    }
}

then的實現比較關鍵,首先有兩個判斷,第一個判斷傳的兩個參數是否都是函數,若是部不是return this執行下一步操做。
第二個判斷的做用是,好比,如今狀態從pending -> rejected;可是中間代碼中有許多個.then的操做,咱們須要跳過這些操做執行.catch的代碼。以下面的代碼,執行結果只會打印1

new Promise((resolve,reject)=>{
    reject(1)
}).then(()=>{
    console.log(2)
}).then(()=>{
    console.log(3)
}).catch((e)=>{
    console.log(e)
})

咱們繼續,接下來看到的是返回了一個新的promise,真正then的實現的確都是返回一個promise實例。這裏很少說

下面有兩個判斷,做用是判斷是rejected仍是fulfilled,首先看fulfilled,若是是fulfilled的話,首先執行fulfilled函數,並把當前的value值傳過去,也就是下面這步操做,res就是傳過去的value值,並執行了(res)=>{console.log(res)}這段代碼;執行完成以後咱們獲得了result;也就是2這個結果,下面就是判斷當前結果是不是一個promise實例了,也就是下面註釋了的狀況,如今咱們直接執行resolve(result);

new Promise((resolve,reject)=>{
    resolve(1)
}).then((res)=>{
    console.log(res)
    return 2
    //return new Promise(resolve=>{})
})

剩下的就很少說了,能夠debugger看看執行結果

catch

class MyPromise {
    ...
    catch(rejected){
        return this.then(null,rejected)
    }
}

完整代碼

class MyPromise {
    constructor(fn){
        if(typeof fn !== 'function') {
            throw new TypeError(`MyPromise fn ${fn} is not a function`)
        }
        this.state = 'pending';
        this.value = void 0;
        fn(this.resolve.bind(this),this.reject.bind(this))
    }
    resolve(value){
        if(this.state !== 'pending') return;
        this.state = 'fulfilled';
        this.value = value
    }
    reject(reason){
        if(this.state !== 'pending') return;
        this.state = 'rejected';
        this.value = reason
    }
    then(fulfilled,rejected){
        if (typeof fulfilled !== 'function' && typeof rejected !== 'function' ) {
            return this;
        }
        if (typeof fulfilled !== 'function' && this.state === 'fulfilled' ||
            typeof rejected !== 'function' && this.state === 'rejected') {
            return this;
        }
        return new MyPromise((resolve,reject)=>{
            if(fulfilled && typeof fulfilled === 'function' && this.state === 'fulfilled'){
                let result = fulfilled(this.value);
                if(result && typeof result.then === 'function'){
                    return result.then(resolve,reject)
                }else{
                    resolve(result)
                }
            }
            if(rejected && typeof rejected === 'function' && this.state === 'rejected'){
                let result = rejected(this.value);
                if(result && typeof result.then === 'function'){
                    return result.then(resolve,reject)
                }else{
                    resolve(result)
                }
            }
        })
    }
    catch(rejected){
        return this.then(null,rejected)
    }
}

測試

new MyPromise((resolve,reject)=>{
    console.log(1);
    //reject(2)
    resolve(2)
    console.log(3)
    setTimeout(()=>{console.log(4)},0)
}).then(res=>{
    console.log(res)
    return new MyPromise((resolve,reject)=>{
        resolve(5)
    }).then(res=>{
        return res
    })
}).then(res=>{
    console.log(res)
}).catch(e=>{
    console.log('e',e)
})
執行結果:
> 1
> 3
> 2
> 5
> 4

原生promise

new Promise((resolve,reject)=>{
    console.log(1);
    //reject(2)
    resolve(2)
    console.log(3)
    setTimeout(()=>{console.log(4)},0)
}).then(res=>{
    console.log(res)
    return new Promise((resolve,reject)=>{
        resolve(5)
    }).then(res=>{
        return res
    })
}).then(res=>{
    console.log(res)
}).catch(e=>{
    console.log('e',e)
})
執行結果:
> 1
> 3
> 2
> 5
> 4

GitHub

wclimb

相關文章
相關標籤/搜索