本身怎样完成promise?

假如让你完成一个 promise ,你会怎么做?

《本身怎样完成promise?》

本身完成promise的大致思绪

  1. 我们要明白我们须要一个异步的操纵要领,满足异步回调。所以挑选到场setTimeout 作为完成的基本, 让函数完成耽误触发。
  2. 坚持一个准绳,掌握 promise 转变状况的只要 promise 组织函数里的 reslove 、 reject 函数。
  3. 链式挪用的道理, 相似jQuery,它会在挪用要领后, return this. 从而构成链式挪用。所以我们采用在挪用then(fn)、 catch(fn) 后 会返回一个新的 promise 对象, 但是 这个 promise 对象 遭到 它的上级promise 对象的状况效果 和 fn 运转效果的掌握。

学问点:
内里 应当 用到点 js 作用域 、 函数闭包、 继续 、 上下文 绑定学问、援用通报。

存在题目

cbList、rhList、 cs 这个三个, Promise 对象能直接接见, 假如对其直接操纵能够形成 顺序杂乱。

代码若有马虎,望人人斧正

var JcPromise = function (fn) {
    // 防备 用户 直接 变动 state
    var state = 'wait'
     // state 为 resolve 状况, 回调函数数组
    var cbList = []
     // state 为 reject 状况, 回调函数数组
    var rjList = []
    this.cbList = cbList
    this.rjList = rjList
    // 
    this.cs = undefined
    // 猎取 promise 的状况
    this.getState = function () {
        return state
    }
    /* 函数闭包,函数 定义在内里, 防备 表面用户 直接 运用 resolve 和 reject; */
    // Promise胜利触发 函数
    var reslove = function (data) {
        this.cs = data
        if (state !== 'wait') {
            return
        } else {
            state = 'solve'
            while (this.cbList.length) {
                cbList.shift()(data)
            }
        }
    }
   // Promise 谢绝 触发函数
    var reject = function (e) {
        this.cs = e
        if (state !== 'wait') {
            return
        } else {
            state = 'reject'
            while (rjList.length) {
                rjList.shift()(e)
            }
        }
    }
// 绑定函数 conext 及 this 为当前 promise对象
    reslove = reslove.bind(this)
    reject = reject.bind(this)
// 耽误 触发
    setTimeout(function () {
        fn(reslove, reject)
    }, 0)
}
JcPromise.prototype.then = function (fn) {
    var handleObj = {}
    var nextPromise = new JcPromise(function (r, j) {
        handleObj.r = r
        handleObj.j = j
    })
    var fixFn = function (data) {
        var result = null
        try {
            result = fn(data)
              // 推断result是否是 JcPromise实例。
            if (result instanceof JcPromise) {
                result.then(function (data) {
                    handleObj.r(data)
                }).catch(function (e) {
                    handleObj.j(e)
                })
            } else  {
                handleObj.r(result)
            }
        } catch (e){
            handleObj.j(e)
        }
    }
    //推断当前状况 假如 是 solve 直接 运转, 假如不是,酒吧 fixFn 推入 cbList 数组。
    if (this.getState() === 'solve') {
        setTimeout(function () {
            fixFn(this.cs)
        }, 0)
    } else {
        this.cbList.push(fixFn)
    }
    return nextPromise
}
JcPromise.prototype.catch = function (fn) {
    var handleObj = {}
    var nextPromise = new JcPromise(function (r, j) {
        handleObj.r = r
        handleObj.j = j
    })
    var fixFn = function (e) {
        var result = null
        try {
            result = fn(e)
            if (result instanceof JcPromise) {
                result.then(function (data) {
                    handleObj.r(data)
                }).catch(function (e) {
                    handleObj.j(e)
                })
            } else {
                handleObj.r(result)
            }
        } catch (e){
            handleObj.j(e)
        }
    }
    if (this.getState() === "reject") {
        setTimeout(function () {
            fixFn(this.cs)
        }, 0)
    } else {
        this.rjList.push(fixFn)
    }
    return nextPromise
}
// 测试代码
var p = new JcPromise(function(r, j) {
    setTimeout(function() {r(100)}, 3000)
}).then(data => {
    console.log('1', data)
    return new JcPromise((r, j) => {
        setTimeout(() => {
            r('hi')
        }, 3000)
    })
}).then(data => console.log('2', data)).then(function () {
    console.log('xxx', xx + 1)
}).catch(e => console.log(e)).then(data => console.log(data, 'end'))

demo 测试
第二版 jcPromise 完成

    var JcPromise = (function() {
        function JcPromise(fn) {
            fn = fn || noop;
            var statusList = ['start', 'pending', 'succeed', 'err'];
            var cbStatus = [0, 1];
            var status = statusList[0];
            var data = null;
            var err = null;
            var that = this;
            var successFn = [];
            var errFn = [];

            function resolve(d) {
                data = d;
                that._changeStatus(2);
            };

            function reject(e) {
                err = e;
                that._changeStatus(3);
            };
            this.getData = function() {
                return data;
            };
            this.getErr = function() {
                return err
            };
            this.getStatus = function() {
                return status
            };
            this._changeStatus = function(idx) {
                switch (status) {
                    case statusList[2]:
                    case statusList[3]:
                        {
                            return false
                        }
                };
                status = statusList[idx];
                if (status === statusList[3]) {
                    setTimeout(function() {
                        that._triggerCatch();
                    }, 0)
                }
                if (status === statusList[2]) {
                    setTimeout(function() {
                        that._triggerThen();
                    }, 0)
                }
            };
            this._pushThenCb = function(cb) {
                successFn.push({
                    status: cbStatus[0],
                    cb: cb
                });
                if (status === statusList[2]) {
                    this._triggerThen();
                }
            };
            this._pushCatchCb = function(cb) {
                errFn.push({
                    status: cbStatus[0],
                    cb: cb
                });
                if (status === statusList[3]) {
                    this._triggerCatch();
                }
            };
            this._triggerThen = function() {
                successFn.map(function(item) {
                    if (item.status === cbStatus[0]) {
                        item.cb(data);
                        item.status = cbStatus[1];
                    }
                })
            };
            this._triggerCatch = function() {
                errFn.map(function(item) {
                    if (item.status === cbStatus[0]) {
                        item.cb(err);
                        item.status = cbStatus[1];
                    }
                })
            };
            this._changeStatus(1);
            this.uuid = uuid++;
            try {
                fn(resolve, reject);
            } catch (e) {
                reject(e)
            }
            return this
        };
        JcPromise.fn = JcPromise.prototype;
        // 返回一个promise
        JcPromise.fn.then = function(cb) {
            var promiseR = null;
            var promiseJ = null;
            var result = null;
            var that = this;
            var fn = function() {
                setTimeout(function() {
                    try {
                        var data = that.getData();
                        result = cb(data);
                        if (typeof result === 'object' && result !== null && result.constructor === JcPromise) {
                            result.then(function(data) {
                                promiseR(data)
                            }).catch(function(e) {
                                promiseJ(e)
                            })
                        } else {
                            promiseR(result)
                        }
                    } catch (e) {
                        promiseJ(e)
                    }
                }, 0);
            };
            this._pushThenCb(fn);
            // 触发promise
            return new JcPromise(function(r, j) {
                promiseR = r;
                promiseJ = j;
            });
        };
        // 返回一个promise
        JcPromise.fn.catch = function(cb) {
            var promiseR = null;
            var promiseJ = null;
            var result = null;
            var that = this;
            var fn = function() {
                setTimeout(function() {
                    try {
                        var data = that.getErr();
                        result = cb(data);
                        if (typeof result === 'object' && result !== null && result.constructor === JcPromise) {
                            result.then(function(data) {
                                promiseR(data)
                            }).catch(function(e) {
                                promiseJ(e)
                            })
                        } else {
                            promiseR(result)
                        }
                    } catch (e) {
                        promiseJ(e)
                    }
                }, 0)
            };
            this._pushCatchCb(fn);
            // 触发promise
            return new JcPromise(function(r, j) {
                promiseR = r;
                promiseJ = j;
            });
        };
        return JcPromise
    })();
    原文作者:L6zt
    原文地址: https://segmentfault.com/a/1190000013753513
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞