手撕promise

源代码 2024-9-25 12:04:07 39 0 来自 中国
观看之前请先认识promise的基本利用
一、分析promise由哪些东西构成

在一样平常的利用中,我们可以知道,一个完备的promise应当包罗乐成、失败、举行中这三个状态,同时尚有resolve,reject两个改变状态的成员函数。末了还会有一个then函数来吸收promise的实验结果
在相识了上述的内容之后,一个promise的雏形就出来了
class myPromise {        constructor(executor) {            //默认状态为pending            this.status = 'pending'            //乐成的默认值为undefined            this.successVal = undefined            //失败的默认值为undefined            this.errorVal = undefined            //初始化时调用传入的回调函数            executor(this.resolve,this.reject)        }        resolve = (data) => {        }        reject = (err) => {        }        then = (success_cb,error_cb) => {        }}这里要分析一下,then函数,大概在一样平常利用中各人都风俗性的只传入一个参数。实在then是有两个参数的,第一个参数是promise乐成时调用,第二个参数是失败时调用。而我们熟知的catch函数,实在内部就是调用的then函数,只不外传入的是失败的回调
catch = (err_cb) => {            this.then(undefined, err_cb)        }下面来完善一下几个函数的内容
        resolve = (data) => {         if (this.status === 'pending') {                this.status = 'success'                this.successVal = data                           }        }        reject = (err) => {          if (this.status === 'pending') {                this.status = 'error'                this.errorVal = err                          }        }        then = (success_cb,error_cb) => {                  setTimeout(() => {                  if (this.status === 'success') {                  success_cb(this.successVal )                  }else if(this.status === 'error'){                   success_cb(this.errorVal )                  }                  })        }如许,一个浅显版的promise就实现了。
接下来就必要去实现promise处置惩罚异步标题。
起首分析一下,出现了异步代码之后会发生什么环境:
通常利用一个有异步的promise会如许
new Promise((resolve,reject)=>{    setTimeout(()=>{        resolve(123)    },2000)})如许我们在调用then的时间实在resolve还没有被实验,promise的状态也并没有变动。以是我们要做的就是讲then函数吸收到的参数存起来,比及promise的状态变了之后再去调用他。如许就能做到处置惩罚异步标题了
        constructor(executor) {            //默认状态为pending            this.status = 'pending'            //乐成的默认值为undefined            this.successVal = undefined            //失败的默认值为undefined            this.errorVal = undefined            //存放乐成的回调函数            this.successCallBackList = []            //存放失败的回调函数            this.errorCallBackList = []            //自动实验一次传入的回调函数            try {                executor(this.resolve, this.reject)            } catch (err) {                this.reject(err)            }        }     resolve = (data) => {            if (this.status === 'pending') {                this.status = 'success'                this.successVal = data                this.successCallBackList.forEach(fn => fn(this.successVal))            }        }        reject = (err) => {            if (this.status === 'pending') {                this.status = 'error'                this.errorVal = err                this.errorCallBackList.forEach(fn => fn(this.errorVal))            }        }        then = (success_cb,error_cb) => {                  setTimeout(() => {                  if (this.status === 'success') {                  success_cb(this.successVal )                  }else if(this.status === 'error'){                   success_cb(this.errorVal )                  }else{                        this.successCallBackList.push(success_cb)                        this.errorCallBackList.push(error_cb)                  }                  })        }上面代码中就是在then里判定当前状态,假如为pending的话就将回调存入对应的数组,然后再resolve和reject函数中去遍历存放回调的数组而且逐一实验里头的函数。
如许异步标题也处置惩罚好了。
接下来就是最告急的处置惩罚then的链式回调了。这也是promise的特色。
起首必要明白的一点是,promise的then函数会返回一个新的promise,如许我们才可以做到不停.then调用。其次,反面的then会拿到上一个then的返回值。
明白了这个概念之后我们就可以去动手写then函数了
        then = (success_cb, error_cb) => {            const promise2 = new myPromise((resolve, reject) => {                    if (this.status === 'success') {                        setTimeout(() => {                            try {                                if (typeof success_cb !== 'function') {                                    resolve(this.successVal)                                } else {                                    let x = success_cb(this.successVal)                                    resolvePromise(promise2, x, resolve, reject)                                }                            } catch (err) {                                reject(err)                            }                        })                    } else if (this.status === 'error') {                        setTimeout(() => {                            try {                                if (typeof error_cb !== 'function') {                                    reject(this.errorVal)                                } else {                                    let x = error_cb(this.errorVal)                                    resolvePromise(promise2, x, resolve, reject)                                }                            } catch (err) {                                reject(err)                            }                        })                    } else {                        this.successCallBackList.push(() => {                            setTimeout(() => {                                try {                                    if (typeof success_cb !== 'function') {                                        resolve(this.successVal)                                    } else {                                        let x = success_cb(this.successVal)                                        resolvePromise(promise2, x, resolve, reject)                                    }                                } catch (err) {                                    reject(err)                                }                            })                        })                        this.errorCallBackList.push(() => {                            setTimeout(() => {                                try {                                    if (typeof error_cb !== 'function') {                                        reject(this.errorVal)                                    } else {                                        let x = error_cb(this.errorVal)                                        resolvePromise(promise2, x, resolve, reject)                                    }                                } catch (err) {                                    reject(err)                                }                            })                        })                    }                }            )            return promise2        }    /**     * @param promise2 promise1.then中返回的新的promise     * @param x promise1中then方法的回调函数返回的值     * @param resolve promise2的reslove回调     * @param reject promise2的reject回调     */    function resolvePromise(promise2, x, resolve, reject) {        if (x === promise2) {            /**             * 假如x等于promis2 则抛出非常,防止陷入死循环 抛出的非常会被上一个promise的then方法捕获到而且直接走reject方法             */            throw new TypeError('Chaining cycle detected for promise');        }        if (x instanceof myPromise) {            /**             * 假如 x 为 Promise ,则使 promise2 担当 x 的状态             * 也就是继承实验x,假如实验的时间拿到一个y,还要继承剖析y             */            x.then(y => {                resolvePromise(promise2, y, resolve, reject)            }, reject)        } else if (x !== null && ((typeof x === 'object') || (typeof x === 'function'))) {            try {                var then = x.then            } catch (e) {                return reject(e)            }            if (typeof then === 'function') {                let called = false //防止多次调用                try {                    then.call(x, y => {                        if (called) return                        called = true                        resolvePromise(promise2, y, resolve, reject)                    }, err => {                        if (called) return                        called = true                        reject(err)                    })                } catch (err) {                    if (called) return                    called = true                    reject(err)                }            } else {                resolve(x)            }        } else {            resolve(x)        }    }resolvePromise函数就是处置惩罚上一个then函数的返回值的工具函数。
then函数里的逻辑大抵上就是,返回一个新的promise,这个新的promise里可以访问到上一个promise的全部属性,同时可以通过调用自身的resolve和reject改变自身的状态,并将上一个promise的then函数的返回值作为参数保存下来,如许他本身的then函数就可以访问到这个值了。也就是我们所说的下一个then能拿到上一个then的返回值。而在then函数中大概返回各种环境的值,以是写了一个resolvePromise函数来处置惩罚各种环境。
以上就是一个完备的promise了。告急的就是明白then函数的链式回调。把这个搞明白了,整个promise也就豁然开朗了。
别的附上完备的代码
/**     * @param promise2 promise1.then中返回的新的promise     * @param x promise1中then方法的回调函数返回的值     * @param resolve promise2的reslove回调     * @param reject promise2的reject回调     */    function resolvePromise(promise2, x, resolve, reject) {        if (x === promise2) {            /**             * 假如x等于promis2 则抛出非常,防止陷入死循环 抛出的非常会被上一个promise的then方法捕获到而且直接走reject方法             */            throw new TypeError('Chaining cycle detected for promise');        }        if (x instanceof myPromise) {            /**             * 假如 x 为 Promise ,则使 promise2 担当 x 的状态             * 也就是继承实验x,假如实验的时间拿到一个y,还要继承剖析y             */            x.then(y => {                resolvePromise(promise2, y, resolve, reject)            }, reject)        } else if (x !== null && ((typeof x === 'object') || (typeof x === 'function'))) {            try {                var then = x.then            } catch (e) {                return reject(e)            }            if (typeof then === 'function') {                let called = false //防止多次调用                try {                    then.call(x, y => {                        if (called) return                        called = true                        resolvePromise(promise2, y, resolve, reject)                    }, err => {                        if (called) return                        called = true                        reject(err)                    })                } catch (err) {                    if (called) return                    called = true                    reject(err)                }            } else {                resolve(x)            }        } else {            resolve(x)        }    }    class myPromise {        //静态resolve方法,可以让利用者直接通过类来访问,不必要实例化这个类。同时以static关键字标识的属性不会被实例继承,只能通过类自身访问        static resolve() {        }        constructor(executor) {            //默认状态为pending            this.status = 'pending'            //乐成的默认值为undefined            this.successVal = undefined            //失败的默认值为undefined            this.errorVal = undefined            //存放乐成的回调函数            this.successCallBackList = []            //存放失败的回调函数            this.errorCallBackList = []            //自动实验一次传入的回调函数            try {                executor(this.resolve, this.reject)            } catch (err) {                this.reject(err)            }        }        resolve = (data) => {            if (this.status === 'pending') {                this.status = 'success'                this.successVal = data                this.successCallBackList.forEach(fn => fn(this.successVal))            }        }        reject = (err) => {            if (this.status === 'pending') {                this.status = 'error'                this.errorVal = err                this.errorCallBackList.forEach(fn => fn(this.errorVal))            }        }        then = (success_cb, error_cb) => {            const promise2 = new myPromise((resolve, reject) => {                    if (this.status === 'success') {                        setTimeout(() => {                            try {                                if (typeof success_cb !== 'function') {                                    resolve(this.successVal)                                } else {                                    let x = success_cb(this.successVal)                                    //浅显处置惩罚then                                    if(x instanceof myPromise){                                        if(x.status==='pending'){                                            x.then()                                        }else{                                            //x的状态不处于pending状态,则将新的promise的resolve和reject作为x的then函数的参数传入                                            //如许,当x的状态变动了,就会调用我们传入的resolve和reject。而且会将x的终极值传入。                                            x.then(resolve, reject)                                        }                                    }else{                                        resolve(x)                                    }                                    // resolvePromise(promise2, x, resolve, reject)                                }                            } catch (err) {                                reject(err)                            }                        })                    } else if (this.status === 'error') {                        setTimeout(() => {                            try {                                if (typeof error_cb !== 'function') {                                    reject(this.errorVal)                                } else {                                    let x = error_cb(this.errorVal)                                    resolvePromise(promise2, x, resolve, reject)                                }                            } catch (err) {                                reject(err)                            }                        })                    } else {                        this.successCallBackList.push(() => {                            setTimeout(() => {                                try {                                    if (typeof success_cb !== 'function') {                                        resolve(this.successVal)                                    } else {                                        let x = success_cb(this.successVal)                                        resolvePromise(promise2, x, resolve, reject)                                    }                                } catch (err) {                                    reject(err)                                }                            })                        })                        this.errorCallBackList.push(() => {                            setTimeout(() => {                                try {                                    if (typeof error_cb !== 'function') {                                        reject(this.errorVal)                                    } else {                                        let x = error_cb(this.errorVal)                                        resolvePromise(promise2, x, resolve, reject)                                    }                                } catch (err) {                                    reject(err)                                }                            })                        })                    }                }            )            return promise2        }        catch = (err_cb) => {            this.then(undefined, err_cb)        }    }
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 16:44, Processed in 0.143121 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表