状态机制
[[PromiseState]] 有三种状态,fulfilled、rejected、pending。
初始值为pending。
状态值一旦改变就不能再改变。
class MyPromise {
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
constructor() {
this.state = MyPromise.PENDING
}
}
MyPromise接受一个回调函数,回调函数接受两个方法,第一个是resolve,第二个是reject。resolve、reject都会接受一个表示结果原因的参数。
[[PromiseResult]]初始值为null。
class MyPromise {
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
constructor(executor) {
this.state = MyPromise.PENDING
this.result = null // 结果
executor(this.resolve, this.reject)
}
resolve(result) {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.FULFILLED
this.result = result
}
}
reject(reason) {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.REJECTED
this.result = reason
}
}
}
resolve、reject被作为回调参数传入executor调用时this绑定会隐性丢失,因为我们知道函数中的this最终会指向调用此函数时的对象。
在严格模式下是undefined,非严格模式下会指向window对象。
let p = new MyPromise((resolve, reject) => {
// ...
resolve('ok') // 调用时this绑定会隐性丢失
})
所以需要将它们的this绑定
class MyPromise {
constructor(executor) {
// ...
executor(this.resolve.bind(this), this.reject.bind(this))
}
}
如果executor执行出错,需要reject掉。
class MyPromise {
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
constructor(executor) {
this.state = MyPromise.PENDING
this.result = null // 结果
try {
executor(this.resolve.bind(this), this.reject.bind(this))
} catch (e) {
this.reject(this.result)
}
}
resolve(result) {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.FULFILLED
this.result = result
}
}
reject(reason) {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.REJECTED
this.result = reason
}
}
}
then方法实现
then接受两个参数onFulFilled,onRejected。
then方法是异步执行的。规范中是用的微任务执行,但是JavaScript没有能直接操控微任务队列的方法,但是可以用宏任务setTimeout代替。
then方法调用的时候状态可能有三种情况,也就是对应着状态机制中的三种状态,需要分别作处理。
class MyPromise {
// ...
then(onFulfilled, onRejected) {
if (this.state === MyPromise.FULFILLED) {
// 状态变为fulfilled时执行onFulfilled
setTimeout(() => {
onFulfilled(this.result)
})
} else if (this.state === MyPromise.REJECTED) {
// 状态变为fulfilled时执行onRejected
setTimeout(() => {
onRejected(this.result)
})
} else {
// ...
}
}
}
当调用then方法resolve,reject还未执行,就是executor中执行了异步的操作,state的状态还为pending时,我们需要让onFulfilled,onRejected回调在恰当的时机,即state状态变更为fulfilled或rejected时才执行。
也就是说then方法调用时状态为pending的话,就要让onFulfilled,onRejected在resolve,reject方法调用的时候才去执行。
class MyPromise {
constructor(executor) {
// ...
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
}
resolve(result) {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.FULFILLED
this.result = result
// 执行pending时传入的onFulfilled
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
}
}
reject(reason) {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.REJECTED
this.result = reason
// 执行pending时传入的onRejected
this.onRejectedCallbacks.forEach(callback => {
callback(reason)
})
}
}
then(onFulfilled, onRejected) {
if (this.state === MyPromise.FULFILLED) {
// 状态变为fulfilled时执行onFulfilled
setTimeout(() => {
onFulfilled(this.result)
})
} else if (this.state === MyPromise.REJECTED) {
// 状态变为fulfilled时执行onRejected
setTimeout(() => {
onRejected(this.result)
})
} else {
// 将两个回调保存起来,等待恰当的时机调用
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
onFulfilled(this.result)
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
onRejected(this.result)
})
})
}
}
}
2.2.7.1 If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).
2.2.7.2 If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason.
2.2.7.3 If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value as promise1.
2.2.7.4 If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason as promise1.
2.2.7.1 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行[[Resolve]](promise2, x)
2.2.7.2 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须以 e 作为原因拒绝
2.2.7.3 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
2.2.7.4 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因
then链式调用
class MyPromise {
constructor(executor) {
// ...
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
}
resolve(result) {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.FULFILLED
this.result = result
// 执行pending时传入的onFulfilled
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
}
}
reject(reason) {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.REJECTED
this.result = reason
// 执行pending时传入的onRejected
this.onRejectedCallbacks.forEach(callback => {
callback(reason)
})
}
}
then(onFulfilled, onRejected) {
if (this.state === MyPromise.FULFILLED) {
// 状态变为fulfilled时执行onFulfilled
setTimeout(() => {
try {
if (typeof onFulfilled !== 'function') {
// 2.2.7.3 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
resolve(this.result)
} else {
// 2.2.7.1 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行[[Resolve]](promise2, x)
let x = onFulfilled(this.result)
resolvePromise(promise2, x)
}
} catch (e) {
// 2.2.7.2 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须以 e 作为原因拒绝
reject(e)
}
})
} else if (this.state === MyPromise.REJECTED) {
// 状态变为fulfilled时执行onRejected
setTimeout(() => {
try {
if (typeof onRejected !== 'function') {
// 2.2.7.4 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因
reject(this.result)
} else {
// 2.2.7.1 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行[[Resolve]](promise2, x)
let x = onRejected(this.result)
resolvePromise(promise2, x)
}
} catch (e) {
// 2.2.7.2 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须以 e 作为原因拒绝
reject(e)
}
});
} else {
// 将两个回调保存起来,等待恰当的时机调用
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
onFulfilled(this.result)
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
onRejected(this.result)
})
})
}
}
}
接下来实现resolvePromise
根据规范的描述
function resolvePromise(promise, x) {
// x等于promise抛出异常,为了防止无限循环
if (x === promise) {
throw new TypeError('错啦')
}
// 如果x是一个promise,那就继续执行
if (x instanceof MyPromise) {
x.then((y) => {
resolvePromise(promise, y)
}, (r) => {
promise.reject(r)
})
} else if (Object.prototype.toString.call(x) === '[object Object]' || typeof x === 'function') {
// 如果是对象或者方法,为了兼容有then方法的类似promise的对象或方法
let then
try {
then = x.then
} catch (e) {
return promise.reject(e)
}
// 2.3.3.3 如果 then 是函数,将 x 作为函数的作用域 this 调用之。传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise
if (typeof then === 'function') {
let called = false
// 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
try {
then.call(
x,
// 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
y => {
// 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
if (called) return
called = true
resolvePromise(promise, y)
},
// 2.3.3.3.2 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
r => {
// 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
if (called) return
called = true
promise.reject(r)
}
)
} catch (e) {
// 2.3.3.3.4 如果调用 then 方法抛出了异常 e
// 2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之
// 2.3.3.3.4.2 否则以 e 为据因拒绝 promise
if (called) return
called = true
promise.reject(e)
}
} else {
// 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise
promise.resolve(x)
}
} else {
// 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise
promise.resolve(x)
}
}
最后优化一下then中的条件分支
最终版
class MyPromise {
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
constructor(executor) {
this.state = MyPromise.PENDING
this.result = null
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
try {
executor(this.resolve.bind(this), this.reject.bind(this))
} catch (e) {
this.reject(this.result)
}
}
resolve(result) {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.FULFILLED
this.result = result
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
}
}
reject(reason) {
if (this.state === MyPromise.PENDING) {
this.state = MyPromise.REJECTED
this.result = reason
this.onRejectedCallbacks.forEach(callback => {
callback(reason)
})
}
}
then(onFulfilled, onRejected) {
let promise2 = new MyPromise((resolve, reject) => {
const handler = (fn, state) => {
setTimeout(() => {
try {
// 2.2.7.3 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
if (typeof fn !== 'function') {
if (state === MyPromise.FULFILLED) {
resolve(this.result)
} else if (state === MyPromise.REJECTED) {
reject(this.result)
}
} else {
// 2.2.7.1 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行[[Resolve]](promise2, x)
let x = fn(this.result)
resolvePromise(promise2, x)
}
} catch (e) {
// 2.2.7.2 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须以 e 作为原因拒绝
reject(e)
}
})
}
if (this.state === MyPromise.FULFILLED) {
handler(onFulfilled, MyPromise.FULFILLED)
} else if (this.state === MyPromise.REJECTED) {
handler(onRejected, MyPromise.REJECTED)
} else {
this.onFulfilledCallbacks.push(() => {
handler(onFulfilled, MyPromise.FULFILLED)
})
this.onRejectedCallbacks.push(() => {
handler(onRejected, MyPromise.REJECTED)
})
}
})
return promise2
}
}
function resolvePromise(promise, x) {
// x等于promise抛出异常,为了防止无限循环
if (x === promise) {
throw new TypeError('错啦')
}
// 如果x是一个promise,那就继续执行
if (x instanceof MyPromise) {
x.then((y) => {
resolvePromise(promise, y)
}, (r) => {
promise.reject(r)
})
} else if (Object.prototype.toString.call(x) === '[object Object]' || typeof x === 'function') {
// 如果是对象或者方法,为了兼容有then方法的类似promise的对象或方法
let then
try {
then = x.then
} catch (e) {
return promise.reject(e)
}
// 2.3.3.3 如果 then 是函数,将 x 作为函数的作用域 this 调用之。传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise
if (typeof then === 'function') {
let called = false
// 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
try {
then.call(
x,
// 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
y => {
// 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
if (called) return
called = true
resolvePromise(promise, y)
},
// 2.3.3.3.2 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
r => {
// 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
if (called) return
called = true
promise.reject(r)
}
)
} catch (e) {
// 2.3.3.3.4 如果调用 then 方法抛出了异常 e
// 2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之
// 2.3.3.3.4.2 否则以 e 为据因拒绝 promise
if (called) return
called = true
promise.reject(e)
}
} else {
// 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise
promise.resolve(x)
}
} else {
// 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise
promise.resolve(x)
}
}
catch
catch就是then(null, noReject)的语法糖。
class MyPromise {
// ...
catch(onReject) {
return this.then(null, onReject)
}
}
finally
finally不管状态如何都会执行也不会接受任何值。
class MyPromise {
// ...
finally(onFinally) {
return this.then((result) => {
// 回调里返回的是Promise需要等待
return MyPromise.resolve(onFinally()).then(() => result)
}, (reason) => {
return MyPromise.resolve(onFinally()).then(() => reason)
})
}
}
Promise.all
Promise.all接受一个可迭代对象,当所有promise的状态都变为fulfilled时,才改变自身状态为fulfilled并返回一个传入的迭代对象的值的数组。
class MyPromise {
// ...
static all(promiseAry) {
let promiseIns = new MyPromise((resolve, reject) => {
let _pAryLen = promiseAry.length,
// 迭代对象
_pAry = Array.from(promiseAry),
// 结果
_pAryResults = new Array(_pAryLen),
_isResolveAll = (() => {
let count = 0
return () => _pAryLen === ++count
})(),
_c = (r, i) => {
// 保持值的位置顺序一致
_pAryResults[i] = r
_isResolveAll() &&
resolve(_pAryResults)
},
_f = (e) => {
reject(e)
};
_pAry.forEach((p, i) => {
p.then((r) => _c(r, i)).catch(_f)
})
})
return promiseIns
}
}
Promise.race
Promise.race接受一个可迭代对象,当其中一个promise的状态变为fulfilled时,才改变自身状态为fulfilled并返回这个对象的值。
class MyPromise {
// ...
static race(promiseAry) {
let promiseIns = new MyPromise((resolve, reject) => {
let _pAry = Array.from(promiseAry)
_pAry.forEach(p => {
p.then((r => {
resolve(r)
})).catch(e => {
reject(e)
})
})
})
return promiseIns
}
}
0