码迷,mamicode.com
首页 > 其他好文 > 详细

Promise简易版实现

时间:2021-01-01 12:43:23      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:简易   索引   eject   promise   else   col   实例   object   resolved   

/**
 * 自定义简易版Promise
 * 
 */
class EasyPromise {
    static resolveCbStatic = undefined; // 供EasyPromise.all等静态方法使用
    static rejectCbStatic = undefined; // 供EasyPromise.all等静态方法使用

    resolveCb = undefined; // status == resolved 的回调
    rejectCb = undefined; // status == reject 的回调
    finallyCb = undefined; // status == resolved || status == reject 的回调,此方法无入参,不依赖于 Promise 的执行结果
    resolveData = undefined; // status == resolved 数据存储
    rejectData = undefined; // status == reject 数据存储
    status = ‘pending‘; // 记录Promise传入的异步任务状态

    constructor (fn) {
        if (!fn || typeof fn != ‘function‘) { 
            console.log(‘EasyPromise方法传参无效‘)
            return false;
        }
        this._resolve = this._resolve.bind(this)
        this._reject = this._reject.bind(this)
        this.then = this.then.bind(this)
        this.catch = this.catch.bind(this)
        this.finally = this.finally.bind(this)

        fn(this._resolve, this._reject)
    }
    _resolve (data) {
        if (this.status == ‘pending‘) {
            this.status = ‘resolved‘;
            this.resolveData = data;
            this.resolveCb && this.resolveCb(data)
            this.finallyCb && this.finallyCb()
        }
    }
    _reject (err) {
        if (this.status == ‘pending‘) {
            this.status = ‘rejected‘;
            this.rejectData = err;
            this.rejectCb && this.rejectCb(data)
            this.finallyCb && this.finallyCb()
        }
    }
    then (fn) {
        if (!fn || typeof fn != ‘function‘) { 
            console.log(‘then方法传参无效‘)
            return false;
        }
        // 链式编程(关键代码)
        return new EasyPromise((resolve, reject) => {
            this.resolveCb = () => {
                let ret = fn(this.resolveData);
                if (ret && ret.constructor == EasyPromise) {
                    ret.then((data) => {
                        resolve(data)
                    })
                } else {
                    resolve(ret)
                }
            };
            if (this.status == ‘resolved‘) {
                this.resolveCb(this.resolveData)
            }
        })
    }
    catch (fn) {
        if (!fn || typeof fn != ‘function‘) { 
            console.log(‘catch方法传参无效‘)
            return false;
        }
        this.rejectCb = fn;
        if (this.status == ‘rejected‘) {
            this.resolveCb(this.rejectData)
        }
        return this; // 链式编程
    }
    finally (fn) {
        if (!fn || typeof fn != ‘function‘) { 
            console.log(‘finally方法传参无效‘)
            return false;
        }
        this.finallyCb = fn;
        if (this.status == ‘resolved‘ || this.status == ‘rejected‘) {
            this.finallyCb()
        }
    }
    static all (promiseList) {
        if (!promiseList || Object.prototype.toString.call([]) != ‘[object Array]‘) { 
            console.log(‘all方法传参无效‘)
            return false;
        }
        let len = promiseList.length;
        let count = 0;
        let res = [];
        let catchFlag = false;
        let invalid = false;
        promiseList.forEach((item) => {
            if (!item || item.constructor != EasyPromise) {
                invalid = true;
            } 
        })
        if (invalid) {
            console.log(‘promiseList 内包含不是EasyPromise的实例‘)
            return false;
        }
        promiseList.forEach((item, index) => {
            if (catchFlag) {
                return false;
            }
            item.then((data) => {
                count += 1;
                res[index] = data;
                if (len == count) { // 所有任务处理成功
                    this.resolveCbStatic(res)
                }
            }).catch(() => { // 任一任务出现错误
                catchFlag = true;
                this.rejectCbStatic(`all 方法调用错误, 对应索引-${index}`)
            })
        })
        return this;
    }
    static then (fn) {
        if (!fn || typeof fn != ‘function‘) { 
            console.log(‘then方法传参无效‘)
            return false;
        }
        this.resolveCbStatic = fn;
        return this;
    }
    static catch (fn) {
        if (!fn || typeof fn != ‘function‘) { 
            console.log(‘catch方法传参无效‘)
            return false;
        }
        this.rejectCbStatic = fn;
    }
    static race (promiseList) {
        if (!promiseList || Object.prototype.toString.call([]) != ‘[object Array]‘) { 
            console.log(‘all方法传参无效‘)
            return false;
        }
        let invalid = false;
        let status;
        promiseList.forEach((item) => {
            if (!item || item.constructor != EasyPromise) {
                invalid = true;
            } 
        })
        if (invalid) {
            console.log(‘promiseList 内包含不是EasyPromise的实例‘)
            return false;
        }
        promiseList.forEach((item, index) => {
            item.then((data) => {
                if (status == ‘end‘) {
                    return false;
                }
                status = ‘end‘;
                this.resolveCbStatic(data)
            }).catch((err) => {
                this.rejectCbStatic(`race 方法调用错误`)
            })
        })
        return this;
    }
}

// 测试EasyPromise
new EasyPromise((resolve, reject) => {
    let data = { value: ‘我是异步响应的数据‘ }
    setTimeout(function () {
        let flag = true;
        if (flag) {
            resolve(data)
        } else {
            reject(‘异步处理异常‘)
        }
    }, 1000)
})
.then((data)  => {
    console.log(`响应数据为:`, data)
    return ‘哈哈哈‘
})
.then((data) => {
    console.log(data, ‘第二个then的数据‘)
    return new EasyPromise((resolve, reject) => {
        setTimeout(function () {
            resolve(‘呵呵呵‘)
        }, 1000)
    })
})
.then((data) => {
    console.log(data, ‘第三个then的数据‘)
})
.catch((err)  => {
    console.log(`发生错误:${err}`)
})
.finally((data)  => {
    console.log(`我是finally触发`)
})

// 测试 EasyPromise.all 方法
let promise1 = new EasyPromise((resolve, reject) => {
    setTimeout(function () {
        resolve(‘呵呵呵‘)
    }, 2000)
})

let promise2 = new EasyPromise((resolve, reject) => {
    setTimeout(function () {
        resolve(‘哈哈哈‘)
    }, 1000)
})
EasyPromise.all([ promise1, promise2 ])
.then((data) => {
    console.log(data)
})
.catch((err) => {
    console.log(err)
})

// 测试 EasyPromise.race 方法
let promise3 = new EasyPromise((resolve, reject) => {
    setTimeout(function () {
        resolve(‘呵呵呵‘)
    }, 2000)
})

let promise4 = new EasyPromise((resolve, reject) => {
    setTimeout(function () {
        resolve(‘哈哈哈‘)
    }, 1000)
})
EasyPromise.race([ promise3, promise4 ])
.then((data) => {
    console.log(data)
})
.catch((err) => {
    console.log(err)
})

 

Promise简易版实现

标签:简易   索引   eject   promise   else   col   实例   object   resolved   

原文地址:https://www.cnblogs.com/qiuYeFengLu/p/14200122.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!