本文主要实现 Promise 的 resolve,reject,以及 then 方法的链式调用,并将会对完成的代码进行测试,最终实现下面的效果
new Promise((resolve,reject)=>{
resolve()
reject()
})
.then(res=>{console.log(res),(err)=>{console.log(err)}}
)
初步实现Promise
- 创建 Promise 类,添加resolve,reject 方法
class Promise {
constructor(executor){
if(typeof executor !== 'function'){
// 参数校验,参数必须是函数
throw new TypeError(`Promise resolver ${executor} is not a function`)
}
// 定义 resolve 函数和 reject 函数
const resolve = function(){}
const reject = function(){}
// 执行传入的函数
executor(resolve,reject)
}
}
module.exports = Promise;
- 完善 resolve,reject 方法
class Promise {
constructor(executor){
if(typeof executor !== 'function'){
// 参数校验,参数必须是函数
throw new TypeError(`Promise resolver ${executor} is not a function`)
}
// 初始化值
this.value = null
this.reason = null
this.status = 'pending'
const resolve = (value)=>{
// 成功后的操作:改变状态,成功后执行回调
if(this.status === 'pendding'){
this.status = 'fulfilled'
this.value = value
}
}
const reject = (reason)=>{
// 失败后的操作:改变状态,失败后执行回调
if(this.status === 'pendding'){
this.status = 'rejected'
this.reason = reason
}
}
// 执行传入的函数
executor(resolve,reject)
}
}
优化代码,绑定 this
class Promise {
constructor(executor){
if (typeof executor !== 'function') {
throw new TypeError(`Promise resolver ${executor} is not a function`)
}
// 初始化值,绑定 this,执行传入的回调
this.initialValue()
this.initBind()
// 防止发生错误
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
initBind() {
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
}
initialValue() {
// 初始化值
this.value = null
this.reason = null
this.status = Promise.PENDING
}
// 定义 resolve 函数和 reject 函数
resolve(value) {
// 成功后的操作:改变状态,成功后执行回调
if (this.status === Promise.PENDING) {
this.status = Promise.FULFILLED
this.value = value
}
}
reject(reason) {
// 失败后的操作:改变状态,失败后执行回调
if (this.status === Promise.PENDING) {
this.status = Promise.REJECTED
this.reason = reason
}
}
}
Promise.PENDING = 'pending'
Promise.FULFILLED = 'fulfilled'
Promise.REJECTED = 'rejected'
初步实现 then 方法
在 promise 中,如果 then 方法未传入参数,在接下来的 then 方法中依然是可以获取结果的
new Promise((resolve,reject) => {
resolve(123)
})
.then()
.then(res=>{
console.log(res) // 输出 123
})
想要实现值得穿透效果,只需要每次将值传出就可以了
then(onFulfilled, onRejected) {
// 值的穿透问题,参数校验
if (typeof onFulfilled !== 'function') {
onFulfilled = function (value) {
return value
}
}
if (typeof onRejected !== 'function') {
onRejected = function (reason) {
throw reason
}
}
if (this.status === Promise.FULFILLED) {
onFulfilled(this.value)
}
if (this.status === Promise.REJECTED) {
onRejected(this.reason)
}
}
实现 then 方法的异步
then(onFulfilled, onRejected) {
// 值的穿透问题,参数校验
if (typeof onFulfilled !== 'function') {
onFulfilled = function (value) {
return value
}
}
if (typeof onRejected !== 'function') {
onRejected = function (reason) {
throw reason
}
}
if (this.status === Promise.FULFILLED) {
// 异步
setTimeout(() => {
onFulfilled(this.value)
})
}
if (this.status === Promise.REJECTED) {
setTimeout(() => {
onRejected(this.reason)
})
}
}
将then 中的回调添加到数组
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
throw new TypeError(`Promise resolver ${executor} is not a function`)
}
this.initialValue()
this.initBind()
// 原生 promise 中异常处理在 reject 函数中
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
initBind() {
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
}
initialValue() {
// 初始化值
this.value = null
this.reason = null
this.status = Promise.PENDING
// 添加成功和时报回调
+ this.onFulfilledCallbacks = []
+ this.onRejectedCallbacks = []
}
// 定义 resolve 函数和 reject 函数
resolve(value) {
// 成功后的操作:改变状态,成功后执行回调
if (this.status === Promise.PENDING) {
this.status = Promise.FULFILLED
this.value = value
+ this.onFulfilledCallbacks.forEach(fn => {
+ fn(this.value)
+ })
}
}
reject(reason) {
// 失败后的操作:改变状态,失败后执行回调
if (this.status === Promise.PENDING) {
this.status = Promise.REJECTED
this.reason = reason
+ this.onRejectedCallbacks.forEach(fn => {
+ fn(this.reason)
+ })
}
}
then(onFulfilled, onRejected) {
// 值得穿透问题,参数校验
if (typeof onFulfilled !== 'function') {
onFulfilled = function (value) {
return value
}
}
+ if (typeof onRejected !== 'function') {
+ onRejected = function (reason) {
+ throw reason
+ }
}
// 实现异步操作
+ if (this.status === Promise.FULFILLED) {
+ setTimeout(() => {
+ onFulfilled(this.value)
+ })
+ }
+ if (this.status === Promise.REJECTED) {
+ setTimeout(() => {
+ onRejected(this.reason)
+ })
+ }
// pending 状态下将要执行的函数放到数组中
+ if (this.status === Promise.PENDING) {
+ this.onFulfilledCallbacks.push((value) => {
+ setTimeout(()=>{
+ onFulfilled(value)
+ })
+ })
+ this.onRejectedCallbacks.push(reason=>{
+ setTimeout(()=>{
+ onRejected(reason)
+ })
+ })
}
}
}
Promise.PENDING = 'pending'
Promise.FULFILLED = 'fulfilled'
Promise.REJECTED = 'rejected'
实现 then 方法返回一个新的 promise,可以在 resolve 中返回一个新的promise
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
throw new TypeError(`Promise resolver ${executor} is not a function`)
}
this.initialValue()
this.initBind()
// 原生 promise 中异常处理在 reject 函数中
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
initBind() {
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
}
initialValue() {
// 初始化值
this.value = null
this.reason = null
this.status = Promise.PENDING
// 添加成功和时报回调
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
}
// 定义 resolve 函数和 reject 函数
resolve(value) {
// 成功后的操作:改变状态,成功后执行回调
if (this.status === Promise.PENDING) {
this.status = Promise.FULFILLED
this.value = value
this.onFulfilledCallbacks.forEach(fn => {
fn(this.value)
})
}
}
reject(reason) {
// 失败后的操作:改变状态,失败后执行回调
if (this.status === Promise.PENDING) {
this.status = Promise.REJECTED
this.reason = reason
this.onRejectedCallbacks.forEach(fn => {
fn(this.reason)
})
}
}
then(onFulfilled, onRejected) {
// 值的穿透问题,参数校验
if (typeof onFulfilled !== 'function') {
onFulfilled = function (value) {
return value
}
}
if (typeof onRejected !== 'function') {
onRejected = function (reason) {
throw reason
}
}
// 实现链式调用,且改变后面的 then 的值,必须通过新的实例
let promise2 = new Promise((resolve, reject) => {
// 实现异步操作
if (this.status === Promise.FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
Promise.resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === Promise.REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason)
Promise.resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
// pending 状态下将要执行的函数放到数组中
if (this.status === Promise.PENDING) {
this.onFulfilledCallbacks.push((value) => {
setTimeout(() => {
try {
let x = onFulfilled(value)
Promise.resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
this.onRejectedCallbacks.push(reason => {
setTimeout(() => {
try {
let x = onRejected(reason)
Promise.resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
})
return promise2
}
}
Promise.PENDING = 'pending'
Promise.FULFILLED = 'fulfilled'
Promise.REJECTED = 'rejected'
Promise.resolvePromise = function (promise2, x, resolve, reject) {
// 避免链式效应
if (promise2 === x) {
reject(new TypeError('Chaining circle detected for promise'))
}
let called = false
if (x instanceof Promise) {
// 判断 x 是否为 promise
x.then(value => {
Promise.resolvePromise(promise2, value, resolve, reject)
}, reason => {
reject(reason)
})
} else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
// 判断 x 是否为对象或者函数
try {
const then = x.then
if (typeof then === 'function') {
then.call(x, value => {
if (called) return
called = true
Promise.resolvePromise(promise2, value, resolve, reject)
}, reason => {
if (called) return
called = true
reject(reason)
})
} else {
if (called) return
called = true
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
resolve(x)
}
}
测试
- 安装测试工具
npm install promises-aplus-tests
// 用来测试自己的promise 符不符合promisesA+规范,mac用户最前面加上sudo
- 添加测试代码
Promise.defer = Promise.deferred = function () {
let dfd = {}
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise;
- 运行测试代码
promises-aplus-tests [js文件名]