美文网首页
Promise - 尝试自己实现(含finally)

Promise - 尝试自己实现(含finally)

作者: 我叫Aliya但是被占用了 | 来源:发表于2019-12-14 20:41 被阅读0次

先把用法写出来

let p = new Pro((resolve, reject) => { 
    // throw new Error('something wrong')
    setTimeout(() => { 
      resolve(11) 
    }, 1000)
    // reject(12)
    
})
p.then(res => { return 99 }, err => {console.log('哦呀呀: ',err); return 888; })
.then(res => console.log('别有用心', res), err => console.log('哦呀呀: ',err))

然后来实现这个简单的

延时、非延时、简单链式

class Pro {
    constructor (fn) {
        this.fn = fn
        this.status = 'pedding'
        this.value = null
        this.errmsg = null
        this.resolveArr = []
        this.rejectArr = []
        this.user_resolve = res => {
            this.resolveArr.length ? this.resolveArr.forEach(item => item[1](item[0](res))) : this.value = res
        }
        this.user_reject = errmsg => {
            this.rejectArr.length ? this.rejectArr.forEach(item => item[1](item[0](errmsg))) : this.errmsg = errmsg
        }
        this.resolve = res => { if (this.status != 'pedding') return; this.status = 'success'; this.user_resolve(res)  }
        this.reject = err => { if (this.status != 'pedding') return; this.status = 'error'; this.user_reject(err) }

        try {
            this.fn(this.resolve, this.reject)
        } catch (e) {
            this.reject(e)
        }
    }
  
    then (resolveFn, rejectFn) {
        if (this.status == 'success') {
            let res = resolveFn(this.value);
            return new Pro(resolve => resolve(res))
        }
        else if (this.status == 'error') {
            let res = rejectFn(this.errmsg);
            return new Pro((resolve, reject) => reject(res))
        }
        else {
            console.log('延时了')
            return new Pro((resolve, reject) => {
                this.resolveArr.push([resolveFn, resolve])
                this.rejectArr.push([rejectFn, reject])
            })
        }
    }
}

复杂链式,then返回promise

p.then(res => { return 99 }, err => {console.log('哦呀呀: ',err); return 888; })
p.then(res => { 
    return new Pro((resolve, reject) => reject('一个promise的返回')) 
}, err => {
    return new Pro((resolve, reject) => resolve('一个promise的错误')) 
})

实现(完整代码在文章末尾)

...
        this.user_resolve = res => {
            this.resolveArr.length 
                ? this.resolveArr.forEach(item => this.__handlerResolve(item[0](res), item[1], item[2])) 
                : this.value = res
        }
        this.user_reject = errmsg => {
            this.rejectArr.length 
                ? this.rejectArr.forEach(item => this.__handlerResolve(item[0](errmsg), item[1], item[2])) 
                : this.errmsg = errmsg
        }
...
            then (resolveFn, rejectFn) {
        if (this.status == 'success') {
            let res = resolveFn(this.value);
            return new Pro(resolve => resolve(res))
            return new Pro((resolve, reject) => this.__handlerResolve(res, resolve, reject))
        }
        else if (this.status == 'error') {
            let res = rejectFn(this.errmsg);
            return new Pro((resolve, reject) => reject(res))
            let err = rejectFn(this.errmsg);
            return new Pro((resolve, reject) => this.__handlerReject(err, resolve, reject))
        }
        else {
            console.log('延时了')
            return new Pro((resolve, reject) => {
                this.resolveArr.push([resolveFn, resolve])
                this.rejectArr.push([rejectFn, reject])
                this.resolveArr.push([resolveFn, resolve, reject])
                this.rejectArr.push([rejectFn, resolve, reject])
            })
        }
    }

    __handlerResolve (res, resolve_fn, reject_fn) {
        if (res instanceof Pro) res.then(res2 => resolve_fn(res2), err => reject_fn(err))
        else resolve_fn(res)
    }
    __handlerReject (err, resolve_fn, reject_fn) {
        if (err instanceof Pro) err.then(res => resolve_fn(res), err2 => reject_fn(err2))
        else reject_fn(err)
    } 
...

catch:then的一个别名

new Pro((resolve, reject) => {      // mise
    throw new Error("别名啊")
}).catch(err => console.log(err))
...
    catch (fn) { return this.then(null, fn) }
...

Promise.resolve 和 Promise.reject

Promise.resolve('right man').then(res => console.log(res))
Promise.reject('loser').catch(res => console.log(res))
Pro.resolve = val => new Pro((resolve, reject) => resolve(val))
Pro.reject = err => new Pro((resolve, reject) => reject(err))

finally(es9)

// finally没入参
Promise.resolve('right man').finally(() => console.log('没参数')).then(res => console.log(res))  //-- right man
Promise.reject('loser').finally(() => console.log('错了也没参数')).catch(res => console.log(res))  //-- loser
// 无论如何都会执行
Promise.resolve('right man').then(res => console.log(res)).finally(() => console.log('没参数'))  
Promise.reject('loser').catch(res => console.log(res)).finally(() => console.log('错了也没参数'))
// (非promise)不影响后续then(走向和参数)
Promise.resolve('right man').finally(() => '没参数').then(res => console.log(res))  //-- right man
Promise.reject('loser').finally(() => '错了也没参数').catch(res => console.log(res))  //-- loser
// promise返回值,执行完成后才会走后续then,可做sleep使用
// promise执行结果reject完全影响后续then,不影响后续then
Promise.resolve('right man').finally(() => {
    return new Promise((reslove, reject) => {
        setTimeout(() => {
            reject('没参数')  //-- (2s后打印) err 没参数
            // reslove('没参数')  //-- (2s后打印) right man
        }, 2000)
    })
}).then(res => console.log(res), err => console.log('err',err))
Promise.reject('loser').finally(() => {
    return new Promise((reslove, reject) => {
        setTimeout(() => {
            reject('没参数')  //-- (2s后打印) err 没参数
            // reslove('没参数')  //-- (2s后打印) err loser
        }, 2000)
    })
}).then(res => console.log(res), err => console.log('err',err))
...
    // 一种特殊的then,fn没入参,(非promise)不影响后续then(走向和参数)
    // promise返回值,执行完成后才会走后续then,可做sleep使用
    // promise执行结果reject完全影响后续then,reslove不影响后续then
    finally (fn) { 
        let handlerFn = (val, iserr) => {
            let fn_return = fn()
            if (fn_return instanceof Pro) {
                return new Pro((resolve, reject) => {  
                    fn_return.then(res => iserr ? reject(val) : resolve(val), err => reject(err))
                })
            } else return val
        }
        return this.then(res => handlerFn(res), err => handlerFn(err, true))
    }
...

race

let p1 = new Promise((resolve, reject) => {      
    setTimeout(() => resolve("p1111"), 1000); 
})
let p2 = new Promise((resolve, reject) => {      
    setTimeout(() => resolve("p2222"), 500); 
})
Promise.race([p1, p2]).then(res => console.log(res), err => console.log('err',err))
//--p2222
Pro.race = function (args) {
    return new Pro((resolve, reject) => {           
        args.forEach(item => {
            if (item && item.then && typeof item.then == 'function')
                item.then(resolve, reject)
            else 
                resolve(item)
        })
    })
}

all

let p1 = new Promise((resolve, reject) => {      
    setTimeout(() => reject("p1111"), 1000); 
})
let p2 = new Promise((resolve, reject) => {      
    setTimeout(() => resolve("p2222"), 500); 
})
Promise.all([1,2, p1, p2]).then(res => console.log(res), err => console.log('err',err))
//--err p1111
//--[ 1, 2, 'p1111', 'p2222' ]
Pro.all = function (args) {
    return new Pro((resolve, reject) => {
        let arr = [], 
            beleft = args.length,
            save = (val, index) => {
                arr[index] = val
                beleft--
                if (beleft == 0) resolve(arr)
            };
        args.forEach((item, index) => {
            if (item && item.then && typeof item.then == 'function')
                item.then(res => save(res, index), err => reject(err))
            else 
                save(item, index)
        })
    })
}

最后加了一些校验,如 promise 不能返回自己、处理变态空链(p.then().then()...)等
地址:https://gitee.com/claudia/Demo/blob/01789eeb644a93e340011bd8846f8dfb70322511/promise/index.js

相关文章

网友评论

      本文标题:Promise - 尝试自己实现(含finally)

      本文链接:https://www.haomeiwen.com/subject/xrwjpctx.html