手写promise

正文

new Promis()时接收一个executor函数作为参数,该函数会立即执行,函数中有两个参数,它们也是函数,分别是resolve和reject,函数同步执行一定要放到try…catch中,否则无法进行错误捕获。

基础框架

function MyPromise(executor) {

  function resolve(value) {

  }

  function reject(reason) {
    
  }

  try {
    executor(resolve, reject);
  } catch (reason) {
    reject(reason);
  }
}

module.exports = MyPromise;

resolve()接收Promise成功值value,reject接收Promise失败原因reason。

MyPromise.js

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function MyPromise(executor) {
    let self = this

    self.state = PENDING
    self.value = null
    self.reason = null
    self.onFulfilledCallbacks = []
    self.onRejectedCallbacks = []
    function resolve(value) {
        if (self.state === PENDING) {
            self.state = FULFILLED
            self.value = value

            self.onFulfilledCallbacks.forEach(function (fulfilledCallback) {
                fulfilledCallback()
            })
        }
    }

    function reject(reason) {
        if (self.state === PENDING) {
            self.state = REJECTED
            self.reason = reason

            self.onRejectedCallbacks.forEach(function (rejectedCallback) {
                rejectedCallback()
            })
        }
    }

    try {
        executor(resolve, reject)
    } catch (reason) {
        reject(reason)
    }
}

// 添加then方法
/**
 * Promise拥有一个then方法,接收两个函数onFulFilled和onRejected,分别
作为Promise成功和失败的回调。所以,在then方法中我们需要对状态state进行判断,
如果是fulfilled,则执行onFulfilled(value)方法,如果是rejected,则执行onRejected(reason)方法。
 */

MyPromise.prototype.then = function (onFulfilled, onRejected) {
    let self = this
    let promise2 = null

    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => {return value}
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}

    promise2 = new MyPromise((resolve, reject) => {
        if (self.state === PENDING) {
            self.onFulfilledCallbacks.push(() => {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(self.value)
                        self.resolvePromise(promise2, x, resolve, reject)
                    } catch (reason) {
                        reject(reason)
                    }
                }, 0);
            })
            self.onRejectedCallbacks.push(() => {
                setTimeout(() => {
                    try {
                        let x = onRejected(self.reason)
                        self.resolvePromise(promise2, x, resolve, reject)
                    } catch (reason) {
                        reject(reason)
                    }
                }, 0);
            })
        }

        if (self.state === FULFILLED) {
            setTimeout(() => {
                try {
                    let x = onFulfilled(self.value)
                    self.resolvePromise(promise2, x, resolve, reject)
                } catch (reason) {
                    reject(reason)
                }
            }, 0);
        }

        if (self.state === REJECTED) {
            setTimeout(() => {
                try {
                    let x = onRejected(self.reason)
                    self.resolvePromise(promise2, x, resolve, reject)
                } catch (reason) {
                    reject(reason)
                }
            }, 0);
        }
    })
    return promise2
}

/**
 * resolvePromise()是用来解析then()回调函数中返回的仍是一个Promise,这个Promise有可能
 * 是我们自己的,有可能是别的库实现的,也有可能是一个具有then()方法的对象,所以这里
 * 靠resolvePromise()来实现统一处理。
 * @param {*} promise2 
 * @param {*} x 
 * @param {*} resolve 
 * @param {*} reject 
 */

MyPromise.prototype.resolvePromise = function(promise2, x, resolve, reject) {
    let self = this
    let called = false // called 防止多次调用

    if (promise2 === x) {
        return reject(new TypeError('循环引用'))
    }

    if (x !== null && Object.prototype.toString.call(x) === '[object Object]' || Object.prototype.toString.call(x) === '[object Function]') {
        // x是对象或者函数
        try {
            let then = x.then

            if (typeof then === 'function') {
                then.call(x, y => {
                    // 别人的Promise的then方法可能设置了getter等,使用called防止多次调用then方法
                    if (called) return
                    called = true
                    // 成功值y有可能还是promise或者是具有then方法等,再次resolvePromise,直到成功值为基本类型或者非thenable
                    self.resolvePromise(promise2, y, resolve, reject)
                }, reason => {
                    if (called) return
                    called = true
                    reject(reason)
                })
            } else {
                if (called) return
                called = true
                resolve(x)
            }
        } catch (reason) {
            if (called) return
            called = true
            reject(reason)
        }
    } else {
        // x是普通值,直接resolve
        resolve(x)
    }
}

/**
 * then()方法的onFulfilled和onRejected回调函数都不是必传项,如果不传,那么我们就无法接收reject(reason)中的错误,
 * 这时我们可以通过链式调用catch()方法用来接收错误。
 * @param {*} onRejected 
 */
MyPromise.prototype.catch = function(onRejected) {
    return this.then(null, onRejected)
}

/**
 * finally是某些库对Promise实现的一个扩展方法,无论是resolve还是reject, 都会走finally方法。
 * @param {*} fn 
 */
MyPromise.prototype.finally = function(fn) {
    return this.then(value => {
        fn()
        return value
    }, reason => {
        fn()
        throw reason
    })
}

/**
 * done方法作为Promise链式调用的最后一步,用来向全局抛出没有被Promise内部捕获的错误,
 * 并且不再返回一个Promise。一般用来结束一个Promise链。
 * @param {*} fn 
 */
MyPromise.prototype.done = function(fn) {
    this.catch(reason => {
        fn()
        throw reason
    })
}

/**
 * Promise.all()接收一个包含多个Promise的数组,当所有Promise均为fulfilled状态时,
 * 返回一个结果数组,数组中结果的顺序和传入的Pronise顺序一一对应。如果有一个Promise为
 * rejected状态,则整个Promise.all为rejected。
 * @param {*} promiseArr 
 */
MyPromise.all = function(promiseArr) {
    return new MyPromise((resolve, reject) => {
        let result = []

        promiseArr.forEach((promise, index) => {
            promise.then(value =>  {
                result[index] = value

                if (result.length === promiseArr.length) {
                    resolve(result)
                }
            }, reject)
        })
    })
}

/**
 * Promise.race()接收一个包含多个Promise的数组,当有一个Promise为fulfilled状态时,
 * 整个大的Promise为onfulfilled,并执行onFulfilled回调函数。如果有一个Promise为rejected
 * 状态,则整个Promise.race为rejected。
 * @param {*} promiseArr 
 */
MyPromise.race = function(promiseArr) {
    return new Promise((resolve, reject) => {
        promiseArr.forEach(promise => {
            promise.then(value => {
                resolve(value)
            }, reject)
        })
    })
}

/**
 * Promise.resolve用来生成一个fulfilled完成态的Promise,一般放在整个Promise链的开头,
 * 用来开始一个Promise链。
 * @param {*} value 
 */
MyPromise.resolve = function(value) {
    let promise = null

    promise = new MyPromise((resolve, reject) => {
        this.prototype.resolvePromise(promise, value, resolve, reject)
    })

    return promise
}

/**
 * Promise.reject用来生成一个rejected失败态的Promise。
 * @param {*} reason 
 */
MyPromise.reject = function(reason) {
    return new MyPromise((resolve, reject) => {
        reject(reason)
    })
}

/**
 * Promise.deferred可以用来延迟执行resolve和reject。
 * 这样就可以在外部通过调用dfd.resolve()和dfd.reject()来决议该Promise。
 */
MyPromise.deferred = function() {
    let dfd = {}
    dfd.promise = new MyPromise((resolve, reject) => {
        dfd.resolve = resolve
        dfd.reject = reject
    })
    return dfd
}

/**
 * stop中返回一个永远不执行resolve或者reject的Promise,那么这个Promise永远处于
 * pending状态,所以永远也不会向下执行then或catch了。这样我们就停止了一个Promise链。
 * 但是这样会有一个缺点,就是链式调用后面的所有回调函数都无法被垃圾回收器回收。
 */
MyPromise.stop = function() {
    return new MyPromise(function() {})
}

module.exports = MyPromise

test.js

let MyPromise = require('./MyPromise.js')

let promise1 = new MyPromise((resolve, reject) => {
    console.log('aaa')
    resolve(123)
})

async function fn() {
    let result = await promise1.then()
    console.log(result)
}
fn()

// let promise2 = new MyPromise((resolve, reject) => {
//     console.log('bbb')
//     setTimeout(() => {
//         reject(222)
//         console.log(222)
//     }, 400);
// })

// let promise3 = new MyPromise((resolve, reject) => {
//     console.log('ccc')
//     setTimeout(() => {
//         resolve(333)
//         console.log(333)
//     }, 500);
// })

// MyPromise.race([promise1, promise2, promise3]).then(value => {
//     console.log('the value:', value)
// }, reason => {
//     console.log('the reason:', reason)
// })

// MyPromise.reject(111).then(value => {
//     console.log('value1', value)
//     return new MyPromise((resolve, reject) => {
//         resolve(222)
//     })
// }).then(value => {
//     console.log('value2:', value)
// }).catch(reason => {
//     console.log('reason:', reason)
// })

参考文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!以下是一个简单的手写Promise的示例: ```javascript class Promise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolveCallbacks = []; this.onRejectCallbacks = []; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onResolveCallbacks.forEach(callback => callback()); } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectCallbacks.forEach(callback => callback()); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { const fulfilledHandler = typeof onFulfilled === 'function' ? onFulfilled : value => value; const rejectedHandler = typeof onRejected === 'function' ? onRejected : reason => { throw reason; }; const promise2 = new Promise((resolve, reject) => { const fulfillHandlerWrapper = () => { setTimeout(() => { try { const result = fulfilledHandler(this.value); resolvePromise(promise2, result, resolve, reject); } catch (error) { reject(error); } }, 0); }; const rejectHandlerWrapper = () => { setTimeout(() => { try { const result = rejectedHandler(this.reason); resolvePromise(promise2, result, resolve, reject); } catch (error) { reject(error); } }, 0); }; if (this.state === 'fulfilled') { fulfillHandlerWrapper(); } else if (this.state === 'rejected') { rejectHandlerWrapper(); } else { this.onResolveCallbacks.push(fulfillHandlerWrapper); this.onRejectCallbacks.push(rejectHandlerWrapper); } }); return promise2; } catch(onRejected) { return this.then(null, onRejected); } } function resolvePromise(promise, result, resolve, reject) { if (promise === result) { return reject(new TypeError('Chaining cycle detected for promise')); } let thenCalledOrThrow = false; if (result instanceof Promise) { result.then( value => resolvePromise(promise, value, resolve, reject), reason => reject(reason) ); } else if (result !== null && (typeof result === 'object' || typeof result === 'function')) { try { const then = result.then; if (typeof then === 'function') { then.call( result, value => { if (thenCalledOrThrow) return; thenCalledOrThrow = true; resolvePromise(promise, value, resolve, reject); }, reason => { if (thenCalledOrThrow) return; thenCalledOrThrow = true; reject(reason); } ); } else { resolve(result); } } catch (error) { if (thenCalledOrThrow) return; thenCalledOrThrow = true; reject(error); } } else { resolve(result); } } ``` 这只是一个基本的实现,还有很多细节和功能可以改进。希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值