Promise简单实现(三)

  1. Promise对象有以下几种状态:
  • pending: 初始状态, 既不是 fulfilled 也不是 rejected.
  • fulfilled: 成功的操作.
  • rejected: 失败的操作.
1).Promise的初步框架
function Promise(executor) {
    let self = this; //缓存this,当前promise的实例
    self.status = 'pending'; //初始状态
    self.value = 'undefined';//默认成功的值
    self.reason = 'undefined';//默认失败的原因

    function resolve(value) { //成功状态
        if (self.status === 'pending') {
            self.status = 'resolved';
            self.value = value;
        }
    }

    function reject(reason) { //失败状态
        if (self.status === 'pending') {
            self.status = 'rejected';
            self.reason = reason;
        }
    }

try{
//因为此函数执行可能会异常,所以需要捕获,如果出错了,需要用错误对象reject
    executor(resolve, reject)
}catch(e){
    reject(e); // 捕获的时候发生异常,就直接失败了
  }
}

Promise.prototype.then = function (onFulfilled, onRjected) {
    let self = this;
    if (self.status === 'resloved') {
        onFulfilled(self.value)
    }
    if (self.status === 'rejected') {
        onRjected(self.reason)
    }
}
2).promise实例可以多次then,当成功后会将then中的成功方法按顺序执行,我们可以先将then中的成功的回调和失败的回调存到数组内,当成功时调用成功的数组即可。
function Promise(executor) {
    let self = this;
    self.status = 'pending';
    self.value = 'undefined';
    self.reason = 'undefined';

------------------------------------------------------------------------------
//此处为增加的代码
    self.onResolvedCallbacks = []; // 存放then成功的回调
    self.onRejectedCallbacks = []; // 存放then失败的回调
------------------------------------------------------------------------------

    function resolve(value) { //成功状态
        if (self.status === 'pending') {
            self.status = 'resolved';
            self.value = value;

------------------------------------------------------------------------------
//此处为增加的代码
            self.onResolvedCallbacks.forEach(function (fn) {
                    fn();
            });
------------------------------------------------------------------------------

        }
    }

    function reject(reason) { //失败状态
        if (self.status === 'pending') {
            self.status = 'rejected';
            self.reason = reason;

------------------------------------------------------------------------------
//此处为增加的代码
            self.onRejectedCallbacks.forEach(function (fn) {
                    fn();
            });
------------------------------------------------------------------------------

        }
    }

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

Promise.prototype.then = function (onFulfilled, onRjected) {
    let self = this;
    if (self.status === 'resloved') {
        onFulfilled(self.value)
    }

    if (self.status === 'rejected') {
        onRjected(self.reason)
    }

------------------------------------------------------------------------------
//此处为增加的代码
    if(self.status === 'pending'){
        self.onResolvedCallbacks.push(function(){
            onFulfilled(self.value)
        })
        self.onRejectedCallbacks.push(function(){
            onRjected(self.reason)
        })
    }
------------------------------------------------------------------------------
}
3).链式调用 jquery,jquery能实现链式调用靠的就是返回this,promise不能返回this,promise实现链式调用靠的是返回一个新的promise
function Promise(executor) {
    let self = this;
    self.status = 'pending';
    self.value = 'undefined';
    self.reason = 'undefined';
    self.onResolvedCallbacks = []; // 存放then成功的回调
    self.onRejectedCallbacks = []; // 存放then失败的回调

    function resolve(value) { //成功状态
        if (self.status === 'pending') {
            self.status = 'resolved';
            self.value = value;
            self.onResolvedCallbacks.forEach(function (fn) {
                fn();
            });
        }
    }

    function reject(reason) { //失败状态
        if (self.status === 'pending') {
            self.status = 'rejected';
            self.reason = reason;
            self.onRejectedCallbacks.forEach(function (fn) {
                fn();
            })
        }
    }
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }

}

Promise.prototype.then = function (onFulfilled, onRjected) {
------------------------------------------------------------------------------
    //我们的代码可以在then中什么都不传promise中值的穿透(实际使用)
    //如果成功和失败默认不传,给一个函数(规范规定)
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {
        return value
    };
    onRjected = typeof onRjected === 'function' ? onRjected : function (err) {
            throw err;
        }
------------------------------------------------------------------------------

        let self = this;
------------------------------------------------------------------------------
//增加的代码
    let promise2; //返回的promise
------------------------------------------------------------------------------

    if (self.status === 'resolved') {
------------------------------------------------------------------------------
//增加的代码
        promise2 = new Promise(function (resolve, reject) {
            // 当成功或者失败执行时有异常那么返回的promise应该处于失败状态
            // x可能是一个promise 也有可能是一个普通的值
            try {
                let x = onFulfilled(self.value);
                // x可能是别人promise,写一个方法统一处理
                resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
                reject(e);
            }
        })
------------------------------------------------------------------------------
    }
    if (self.status === 'rejected') {
------------------------------------------------------------------------------
//增加的代码  
        promise2 = new Promise(function (resolve, reject) {
            try {
                let x = onRjected(self.reason);
                resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
                reject(e);
            }
        })
------------------------------------------------------------------------------
        
    }
    if (self.status === 'pending') {
        self.onResolvedCallbacks.push(function () {
------------------------------------------------------------------------------
//增加的代码            
            try {
                let x = onFulfilled(self.value);
                resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
                reject(e)
            }
        })
        self.onRejectedCallbacks.push(function () {
            try {
                let x = onRjected(self.reason);
                resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
                reject(e);
            }
------------------------------------------------------------------------------
        })
    }
------------------------------------------------------------------------------
//增加的代码
    return promise2;
------------------------------------------------------------------------------
}
4).解析then中的结果
function resolvePromise(promise2, x, resolve, reject) {
    // 有可能这里返回的x是别人的promise
    // 尽可能允许其他乱写
    //返回的结果和promise是同一个那么永远不会成功和失败
    if (promise2 === x) { //这里应该报一个类型错误,有问题
        return reject(new TypeError('循环引用了'))
    }
    // 看x是不是一个promise,promise应该是一个对象
   //有些人写的promise可能会既调用成功 又调用失败,如果两个都调用先 调用谁另一个就忽略掉
    let called; // 表示是否调用过成功或者失败
  
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        // 可能是promise {},看这个对象中是否有then方法,如果有then我就认为他是promise了
        try { // {then:1}
            let then = x.then;
            if (typeof then === 'function') {
                // 成功
                then.call(x, function (y) {
                    if (called) return
                    called = true
                    // y可能还是一个promise,在去解析直到返回的是一个普通值
                    resolvePromise(promise2, y, resolve, reject)
                }, function (err) { //失败
                    if (called) return
                    called = true
                    reject(err);
                })
            } else {
                resolve(x)
            }
        } catch (e) {
            if (called) return
            called = true;
            reject(e);
        }
    } else { // 说明是一个普通值1
        resolve(x); // 表示成功了
    }
}
如果then中无论是成功的回调还是失败的回调只要返回了结果就会走下一个then中的成功,如果有错误走下一个then的失败
如果第一个promise返回一个普通值,会进到下一次then的成功的回调,如果第一个promise返回了一个promise,需要等待返回的promise执行后的结果传递给下一次then中
6).捕获错误的方法
Promise.prototype.catch = function (callback) {
    return this.then(null, callback)
}
7).Promise的静态方法
  • all:全部成功才算成功
Promise.all = function (promises) {
    //promises是一个promise的数组
    return new Promise(function (resolve, reject) {
        let arr = []; //arr是最终返回值的结果
        let i = 0; // 表示成功了多少次
        function processData(index, y) {
            arr[index] = y;
            if (++i === promises.length) {
                resolve(arr);
            }
        }
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(function (y) {
                processData(i, y)
            }, reject)
        }
    })
}
  • race:只要有一个promise成功了 就算成功。如果第一个失败了就失败了
Promise.race = function (promises) {
    return new Promise(function (resolve, reject) {
        for (var i = 0; i < promises.length; i++) {
            promises[i].then(resolve,reject)
        }
    })
}
  • resolve:生成一个成功的promise
Promise.resolve = function(value){
    return new Promise(function(resolve,reject){
        resolve(value);
    })
}
  • reject:生成一个失败的promise
Promise.reject = function(reason){
    return new Promise(function(resolve,reject){
        reject(reason);
    })
}
8).promise规范中要求,所有的onFufiled和onRjected都需要异步执行,setTimeout(在onFufiled和onRjected处添加setTimeout)
Promise.prototype.then = function (onFulfilled, onRjected) {
    //成功和失败默认不穿给一个函数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {
        return value;
    }
    onRjected = typeof onRjected === 'function' ? onRjected : function (err) {
        throw err;
    }
    let self = this;
    let promise2; //返回的promise
    if (self.status === 'resolved') {
        promise2 = new Promise(function (resolve, reject) {
            // 当成功或者失败执行时有异常那么返回的promise应该处于失败状态
            // x可能是一个promise 也有可能是一个普通的值
-------------------------------------------------------------------------------------------------
            setTimeout(function () {
                try {
                    let x = onFulfilled(self.value);
                    // x可能是别人promise,写一个方法统一处理
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            })
        })
    }
    if (self.status === 'rejected') {
        promise2 = new Promise(function (resolve, reject) {
            setTimeout(function () {
                try {
                    let x = onRjected(self.reason);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            })

        })
    }
    // 当调用then时可能没成功 也没失败
    if (self.status === 'pending') {
        promise2 = new Promise(function (resolve, reject) {
            // 此时没有resolve 也没有reject
            self.onResolvedCallbacks.push(function () {
                setTimeout(function () {
                    try {
                        let x = onFulfilled(self.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                })
            });
            self.onRejectedCallbacks.push(function () {
                setTimeout(function () {
                    try {
                        let x = onRjected(self.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                })
            });
        })
    }
-------------------------------------------------------------------------------------------------
    return promise2;
}
9).promise测试

下载一个Promise的测试库,promises-aplus-tests

  • npm install -g promises-aplus-tests
  • promises-aplus-tests 文件名
测试需要添加的代码
Promise.defer = Promise.deferred = function () {
    let dfd = {};
    dfd.promise = new Promise(function (resolve, reject) {
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
    return dfd
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • Promise 对象 Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函...
    neromous阅读 8,698评论 1 56
  • 目录:Promise 的含义基本用法Promise.prototype.then()Promise.prototy...
    BluesCurry阅读 1,488评论 0 8
  • 00、前言Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区...
    夜幕小草阅读 2,127评论 0 12
  • Promiese 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,语法上说,Pr...
    雨飞飞雨阅读 3,348评论 0 19
  • 项目结构图如下: 下面分步骤一一讲解:第一步,在pom.xml中添加相应依赖: <?xml version="1....
    simple_xuan阅读 512评论 0 0