实现符合promiseA+规范的promise

 1.promiseA+约定的规范

参考链接:http://promisesaplus.com/

术语:

  • promise:是一个具有then方法的对象或者是函数,它的行为符合该规范
  • thenable:是一个定义了then方法的对象或者函数
  • value:可以是任何一个合法的js值(包括undifened)
  • exception:是一个异常,是在promise里面可以用throw语句抛出来的值
  • reason:是一个promise里reject之后返回的拒绝原因

一个Promise有三种状态:pending,fulfilled和rejected,

当状态为pending时,可以转为fulfilled或者是rejected状态之一;当状态为fulfilled时,就不能转换为其他状态了,必须返回一个不能改变的值;当状态为reject时,同样也不能转换为其他状态,必须有一个被拒绝的原因值也不能改变。

一个Promise必须拥有一个then方法来访问它的值或者拒绝原因。

Promise(onFufilled, onRejected)

这两个参数都是可选参数,传入的onFuilled和onRejected都必须是函数的形式,如果不是,就此忽略。

如果onFufilled是函数,则当Promise执行结束之后必须被调用,最终返回值为value,其调用次数不超过一次,而onRejected返回的是reason。

then()方法可以被一个Promise对象多次调用且必须返回一个Promise对象。

promise2 = promise1.then(onFulfilled,onRejected)

2. 手写实现PromiseA+规范

//  实现promise构造函数部分
try {
    module.export = Promise
} catch (error) {
}
function Promise(executor) {
    // self是指window或是全局作用域self = this,那self指的是当前函数作用域?
    var self = this
    self.status = 'pending' // 当前promise状态
    self.data = undefined // promise的初始化值
    self.onResolvedCallback = [] // Promise状态为resolve时的回调函数集
    self.onRejectedCallback = [] // Promise状态为rejected时的回调函数集
    executor(resolve, reject) // 执行executor并传入参数
    // 在构造函数中需要完善resolve和reject两个函数
    function resolve(value) {
        // 如果状态为pendding,将状态改为resolved
        setTimeout(function () {// 异步执行所有回调函数
            if (self.status == "pending") {
                self.status = 'resolved'
                self.data = value
                for (var i = 0; i < self.onResolvedCallback.length; i++) {
                    self.onResolvedCallback[i](value)
                }
            }
        })
    }

    function reject(reson) {
        // 异步执行回调函数
        setTimeout(function () {
            if (self.status = 'pending') {
                self.status = 'rejected'
                self.data = reson
                for (var i = 0; i < self.onRejectedCallback.length; i++) {
                    self.onRejectedCallback[i](reson)
                }
            }
        });
    }
    try {
        executor(resolve, reject) // 执行executor
    } catch (error) {
        reject(error)
    }
}

function resolvePromise(promise2, x, resolve, reject) {
    var then
    var thenCalledOrThrow = false
    if (promise2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise!'))
    }
    if (x instanceof Promise) {
        if (x.status === 'pending') {
            x.then(function (v) {
                resolvePromise(promise2, v, resolve, reject)
            }, reject)
        } else {
            x.then(resolve, reject)
        }
        return
    }
    if ((x !== null) && ((typeof x === 'object') || (typeof x === 'function'))) {
        try {
            then = x.then
            if (typeof then === 'function') {
                then.call(x, function rs(y) {
                    if (thenCalledOrThrow) return
                    thenCalledOrThrow = true
                    return resolvePromise(promise2, y, resolve, reject)
                }, function rj(r) {
                    if (thenCalledOrThrow) return
                    thenCalledOrThrow = true
                    return reject(r)
                })
            } else {
                resolve(x)
            }
        } catch (error) {
            if (thenCalledOrThrow) return
            thenCalledOrThrow = true
            return reject(error)
        }
    } else {
        resolve(x)
    }

}
// 实现then方法
// then()方法是promise执行之后可以拿到value或是reason的方法,并且还要保证then执行后仍返回一个promise的方法
// then()还要支持多次调用
// then()方法接收两个函数作为参数,onResolve和onRejected,分别作为promise成功或失败后的回调
// 注意onResolved和onRejected需要进行异步调用
Promise.prototype.then = function (onResolved, onRejected) {
    var self = this
    var promise2
    // 根据标准,如果回调不是函数则忽略
    onResolved = typeof onResolved === 'function' ? onResolved : function (value) {
        return value
    }
    onRejected = typeof onRejected === 'function' ? onRejected : function (reason) {
        return reason
    }
    if (self.status === 'resolved') {
        // 如果已经确定promise返回状态为resolved,我们则调用onResolved,考虑有throw,则包裹在try-catch中
        return promise2 = new Promise(function (resolve, reject) {
            setTimeout(function () {
                // 异步调用onResolved
                try {
                    var x = onResolved(self.data)
                    if (x instanceof Promise) {
                        // 如果x的返回值是一个promise对象,直接取它的结果作为promise2的结果
                        x.then(resolve, reject)
                    }
                    resolve(x) // 否则以它的返回值作为promise2的结果
                } catch (error) {
                    reject(error) // 如果出错,以捕捉到的错误作为promise2的结果
                }
            })
        })
    }
    if (self.status === 'rejected') {
        return promise2 = new Promise(function (resolve, reject) {
            setTimeout(function () {
                try {
                    var x = onRejected(self.date)
                    if (x instanceof Promise) {
                        x.then(resolve, reject)
                    }
                } catch (error) {
                    reject(error)
                }
            })
        })
    }
    if (self.status === 'pending') {
        // 如果当前promise处于pending状态,我们不确定是调用onResolve还是onRejected
        // 需要等到promise的状态确定后,才能知道如何处理
        return promise2 = new Promise(function (resolve, reject) {
            self.onResolvedCallback.push(function (value) {
                try {
                    var x = onResolved(self.data)
                    if (x instanceof Promise) {
                        x.then(resolve, reject)
                    }
                } catch (error) {
                    reject(error)
                }
            })
            self.onRejectedCallback.push(function (reason) {
                try {
                    var x = onRejected(self.data)
                    if (x instanceof Promise) {
                        x.then(resolve, reject)
                    }
                } catch (error) {
                    reject(error)
                }
            })
        })
    }
}

Promise.prototype.catch = function (onRejected) {
    return this.then(null, onRejected)
}
// 最后这个是测试用的
Promise.deferred = Promise.defer = function(){
    var dfd = {}
    dfd.promise = new Promise(function(resolve, reject){
        dfd.resolve = resolve
        dfd.reject = reject
    })
    return dfd
}
// 最后执行测试的方法是

3. 测试方法

手写实现的Promise,文件名是Promise.js

npm i -g promises-aplus-tests

promises-aplus-tests Promise.js

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值