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