promise封装

82 阅读5分钟

大致框架

const p = new Promise((resolve,reject)=>{
    resolve('ok')
})
function Promise(func){
    function resolve(data){

    }
    function reject(data){
        
    }
    func(resolve,reject)
}



resolve和rejected基本功能搭建

const p = new Promise((resolve,reject)=>{
    resolve('ok')
})
console.log(p);
function Promise(func){
    this.PromiseState = 'pending'
    this.PromiseResult = null
    // this保存
    const self = this
    function resolve(data){
        self.PromiseState = 'fulfilled'
        self.PromiseResult = data
    }
    function reject(data){
        self.PromiseState = 'rejected'
        self.PromiseResult = data
    }
    func(resolve,reject)
}

image.png



抛异常

const p = new Promise((resolve,reject)=>{
    throw 'error'
})
console.log(p);
function Promise(func){
    this.PromiseState = 'pending'
    this.PromiseResult = null
    // this保存
    const self = this
    function resolve(data){
        self.PromiseState = 'fulfilled'
        self.PromiseResult = data
    }
    function reject(data){
        self.PromiseState = 'rejected'
        self.PromiseResult = data
    }
    try{
        func(resolve,reject)
    }catch(e){
        reject(e)
    }
}

image.png

状态变更后不可变更

const p = new Promise((resolve,reject)=>{
    resolve('ok')
    reject('error')
})
console.log(p);
function Promise(func){
    this.PromiseState = 'pending'
    this.PromiseResult = null
    // this保存
    const self = this
    function resolve(data){
        if(self.PromiseState!=='pending')return
        self.PromiseState = 'fulfilled'
        self.PromiseResult = data
    }
    function reject(data){
        if(self.PromiseState!=='pending')return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
    }
    try{
        func(resolve,reject)
    }catch(e){
        reject(e)
    }
}

image.png

then方法封装

const p = new Promise((resolve,reject)=>{
    throw 'error'
})
p.then(value=>{
    console.log(value);
},reason=>{
    console.log(reason);
})
function Promise(func){
    this.PromiseState = 'pending'
    this.PromiseResult = null
    // this保存
    const self = this
    function resolve(data){
        if(self.PromiseState!=='pending')return
        self.PromiseState = 'fulfilled'
        self.PromiseResult = data
    }
    function reject(data){
        if(self.PromiseState!=='pending')return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
    }
    try{
        func(resolve,reject)
    }catch(e){
        reject(e)
    }
}
Promise.prototype.then = function(resolve,reject){
    if(this.PromiseState==='fulfilled'){
        resolve(this.PromiseResult)
    }
    if(this.PromiseState==='rejected'){
        reject(this.PromiseResult)
    }
}

image.png

异步

const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("ok");
    },1000);
});
p.then(
    (value) => {
        console.log(value);
    },
    (reason) => {
        console.log(reason);
    }
);
function Promise(func) {
    this.PromiseState = 'pending'
    this.PromiseResult = null
    // 当异步时,将then方法里的参数保存下来
    this.callbacks = {}
    // this保存
    const self = this
    function resolve(data) {
        // 异步时执行then方法里面的参数(函数)
        if(self.callbacks.onResolve){
            self.callbacks.onResolve(data)
        }
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'fulfilled'
        self.PromiseResult = data
    }
    function reject(data) {
        if(self.callbacks?.onReject){
            self.callbacks.onReject(data)
        }
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
    }
    try {
        func(resolve, reject)
    } catch (e) {
        reject(e)
    }
}
Promise.prototype.then = function (resolve, reject) {
    if (this.PromiseState === 'fulfilled') {
        resolve(this.PromiseResult)
    }
    if (this.PromiseState === 'rejected') {
        reject(this.PromiseResult)
    }
    // 当异步时,state状态为pending,将参数保存在callbacks
    if (this.PromiseState === 'pending') {
        this.callbacks = {
            onResolve: resolve,
            onReject: reject
        }
    }
}

1s过后

image.png

同步修改then方法返回结果

const p = new Promise((resolve, reject) => {
    resolve('ok')
});
const result = p.then(
    (value) => {
        return new Promise((resolve,reject)=>{
            throw 'errors'
        })
    },
    (reason) => {
        console.log('reject');
    }
);
console.log(result);

目前封装的输出结果为

image.png

预期的输出结果为

image.png

所以更改之后的代码为

const p = new Promise((resolve, reject) => {
    resolve("ok");
});
const result = p.then(
    (value) => {
        return new Promise((resolve, reject) => {
            throw "errors";
        });
    },
    (reason) => {
        console.log("reject");
    }
);
console.log(result);
function Promise(func) {
    this.PromiseState = 'pending'
    this.PromiseResult = null
    // 当异步时,将then方法里的参数保存下来
    this.callbacks = {}
    // this保存
    const self = this
    function resolve(data) {
        if (self.callbacks.onResolve) {
            self.callbacks.onResolve(data)
        }
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'fulfilled'
        self.PromiseResult = data
    }
    function reject(data) {
        if (self.callbacks?.onReject) {
            self.callbacks.onReject(data)
        }
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
    }
    try {
        func(resolve, reject)
    } catch (e) {
        reject(e)
    }
}
let data = null
Promise.prototype.then = function (resolve, reject) {
    const func = (diffResolve, diffReject) => {
        if (this.PromiseState === 'fulfilled') {
            try {
                const result = resolve(this.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        diffResolve(v)
                    }, r => {
                        diffReject(r)
                    })
                } else {
                    diffResolve(result)
                }
            } catch (e) {
                diffReject(e)
            }
        }
        if (this.PromiseState === 'rejected') {
            try {
                const result = reject(this.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        diffResolve(v)
                    }, r => {
                        diffReject(r)
                    })
                } else {
                    diffResolve(result)
                }
            } catch (e) {
                diffReject(e)
            }
        }
        // 当异步时,state状态为pending,将参数保存在callbacks
        if (this.PromiseState === 'pending') {
            this.callbacks = {
                onResolve: resolve,
                onReject: reject
            }
        }
    }
    return new Promise(func)
}

image.png

在返回值为promise时,标记的resolve处于递归中,调用的是递归前的函数(标记),所以参数v值为this.PromiseResult image.png

异步修改then方法返回结果

const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("ok");
    }, 100);
});
const result = p.then(
    (value) => {
        return new Promise((resolve, reject) => {
            throw "errors";
        });
    },
    (reason) => {
        console.log("reject");
    }
);
console.log(result);
function Promise(func) {
    this.PromiseState = 'pending'
    this.PromiseResult = null
    // 当异步时,将then方法里的参数保存下来
    this.callbacks = []
    // this保存
    const self = this
    function resolve(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'fulfilled'
        self.PromiseResult = data
        if (self.callbacks.length > 0) {
            self.callbacks.forEach((item) => {
                item.onResolve(data)
            })
        }
    }
    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
        if (self.callbacks.length > 0) {
            self.callbacks.forEach((item) => {
                item.onReject(data)
            })
        }
    }
    try {
        func(resolve, reject)
    } catch (e) {
        reject(e)
    }
}
Promise.prototype.then = function (resolve, reject) {
    const self = this
    const func = (diffResolve, diffReject) => {
        if (this.PromiseState === 'fulfilled') {
            try {
                const result = resolve(this.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        diffResolve(v)
                    }, r => {
                        diffReject(r)
                    })
                } else {
                    diffResolve(result)
                }
            } catch (e) {
                diffReject(e)
            }
        }
        if (this.PromiseState === 'rejected') {
            try {
                const result = reject(this.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        diffResolve(v)
                    }, r => {
                        diffReject(r)
                    })
                } else {
                    diffResolve(result)
                }
            } catch (e) {
                diffReject(e)
            }
        }
        // 当异步时,state状态为pending,将参数保存在callbacks
        if (this.PromiseState === 'pending') {
            this.callbacks.push({
                onResolve: function () {
                    try {
                        const result = resolve(self.PromiseResult)
                        if (result instanceof Promise) {
                            result.then(v => {
                                diffResolve(v)
                            }, r => {
                                diffReject(r)
                            })
                        } else {
                            diffResolve(result)
                        }
                    } catch (e) {
                        diffReject(e)
                    }
                },
                onReject: function () {
                    try {
                        const result = reject(self.PromiseResult)
                        if (result instanceof Promise) {
                            result.then(v => {
                                diffResolve(v)
                            }, r => {
                                diffReject(r)
                            })
                        } else {
                            diffResolve(result)
                        }
                    } catch (e) {
                        diffReject(e)
                    }
                },
            })
        }
    }
    return new Promise(func)
}

image.png

then方法优化

Promise.prototype.then = function (resolve, reject) {
    const func = (diffResolve, diffReject) => {
        const command = (type) => {
            try {
                const result = type(this.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        diffResolve(v)
                    }, r => {
                        diffReject(r)
                    })
                } else {
                    diffResolve(result)
                }
            } catch (e) {
                diffReject(e)
            }
        }
        if (this.PromiseState === 'fulfilled') {
            command(resolve)
        }
        if (this.PromiseState === 'rejected') {
            command(reject)
        }
        // 当异步时,state状态为pending,将参数保存在callbacks
        if (this.PromiseState === 'pending') {
            this.callbacks.push( {
                onResolve: () => {
                    command(resolve)
                },
                onReject: () => {
                    command(reject)
                }
            })
        }
    }
    return new Promise(func)
}

catch方法与异常穿透

const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("123");
    });
});
p.then((res) => {
    throw "error";
})
    .then()
    .catch((res) => {
        console.log(111, res);
    });
Promise.prototype.then = function (resolve, reject) {
    if (typeof resolve !== 'function') {
        resolve = value => value
    }
    if (typeof reject !== 'function') {
        reject = reason => {
            throw reason
        }
    }
   ...
}

Promise.prototype.catch = function (onReject) {
    return this.then(undefined, onReject)
}

image.png

resolve方法实现

const p = Promise.resolve("ok");
console.log(p);
Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            resolve.then(res => {
                resolve(res)
            }, rej => {
                reject(rej)
            })
        } else {
            resolve(value)
        }
    })
}

image.png

resolve方法的返回值状态是根据最后一个promise对象的结果来进行判断的

如:

const p = Promise.resolve(
new Promise((res, rej) => {
    rej("error");
})
);
console.log(p);

image.png

reject封装

const p = Promise.reject("error");
const p2 = Promise.reject(
    new Promise((res, rej) => {
        res("ok");
    })
);
console.log(p, p2);
Promise.reject = function (value) {
    return new Promise((resolve, reject) => {
        reject(value)
    })
}

image.png

不管参数是什么,返回的state状态都为rejected

all方法封装

const p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("ok");
    }, 1000);
});
const p2 = Promise.resolve("success");
const p3 = Promise.resolve("Oh yeah");
const p4 = Promise.reject("error");
const result1 = Promise.all([p1, p2, p3]);
const result2 = Promise.all([p1, p2, p3, p4]);
console.log(result1);
console.log(result2);
Promise.all = function (value) {
    return new Promise((resolve, reject) => {
        let num = 0
        const arr = []
        value.forEach((item, index) => {
            item.then(res => {
                num++
                arr[index] = res
                if (num === value.length) {
                    resolve(arr)
                }
            }, rej => {
                reject(rej)
            })
        })
    })
}

image.png

如果数组里面的promise实例都执行resolve,那么状态就为fulfilled,值为数组里面的所有返回值,反之若有一个执行reject方法,状态就为rejected,值为第一个执行rejected方法的返回值

race方法封装

const p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("ok");
    }, 1000);
});
const p2 = Promise.resolve("success");
const p3 = Promise.resolve("Oh yeah");
const result = Promise.race([p1, p2, p3]);
console.log(result);
Promise.race = function (value) {
    return new Promise((resolve, reject) => {
        value.forEach((item) => {
            item.then(res => {
                resolve(res)
            }, rej => {
                reject(rej)
            })
        })
    })
}

image.png 将状态和值改成第一个执行的返回值和状态

promise异步执行

const p1 = new Promise((resolve, reject) => {
    resolve("ok");
    console.log(1111);
});
p1.then((res) => {
    console.log(2222);
});
console.log(3333);
function Promise(func) {
    this.PromiseState = 'pending'
    this.PromiseResult = null
    // 当异步时,将then方法里的参数保存下来
    this.callbacks = []
    // this保存
    const self = this
    function resolve(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'fulfilled'
        self.PromiseResult = data
        setTimeout(() => {
            self.callbacks.forEach((item) => {
                item.onResolve(data)
            })
        })
    }
    function reject(data) {
        if (self.PromiseState !== 'pending') return
        self.PromiseState = 'rejected'
        self.PromiseResult = data
        setTimeout(() => {
            self.callbacks.forEach((item) => {
                item.onReject(data)
            })
        })
    }
    try {
        func(resolve, reject)
    } catch (e) {
        reject(e)
    }
}


Promise.prototype.then = function (resolve, reject) {
    if (typeof resolve !== 'function') {
        resolve = value => value
    }
    if (typeof reject !== 'function') {
        reject = reason => {
            throw reason
        }
    }
    const func = (diffResolve, diffReject) => {
        const command = (type) => {
            try {
                const result = type(this.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        diffResolve(v)
                    }, r => {
                        diffReject(r)
                    })
                } else {
                    diffResolve(result)
                }
            } catch (e) {
                diffReject(e)
            }
        }
        if (this.PromiseState === 'fulfilled') {
            setTimeout(() => {
                command(resolve)
            })
        }
        if (this.PromiseState === 'rejected') {
            setTimeout(() => {
                command(reject)
            })
        }
        // 当异步时,state状态为pending,将参数保存在callbacks
        if (this.PromiseState === 'pending') {
            this.callbacks.push({
                onResolve: () => {
                    command(resolve)
                },
                onReject: () => {
                    command(reject)
                }
            })
        }
    }
    return new Promise(func)
}

image.png