promise实现:
首先创建一个 MyPromise
类
class MyPromise {
constructor(executor) {
this.state = 'pending' // 状态
this.value = undefined // 保存 resolve 的值
this.error = undefined // 保存 reject 的值
// resolve 函数
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fullFilled'
this.value = value
}
}
// reject 函数
const reject = error => {
if (this.state === 'pending') {
this.state = 'rejected'
this.error = error
}
}
// 执行通过 new MyPromise() 传进来函数
executor(resolve, reject)
}
// then 方法
then(onFullFilled, onRejected) {
// 如果状态为 fullFilled,执行 resolve 回调
if (this.state === 'fullFilled') {
onFullFilled(this.value)
}
// 如果状态为 fullFilled,执行 reject 回调
if (this.state === 'rejected') {
onRejected(this.error)
}
}
}
// 测试基础功能
new MyPromise((resolve, reject) => {
if (Math.random() < 0.5) {
resolve('fullFilled')
} else {
reject('rejected')
}
}).then(value => {
console.log(value)
}, error => {
console.log(error)
})
复制代码
以上代码,姑且实现最简单的 resolve
和reject
,但是在Promise
中,如果有语法错误,是会被捕获,然后触发reject
的,所以还需要加上错误捕获
实现错误捕获
try {
// 执行通过 new MyPromise() 传进来函数
executor(resolve, reject)
} catch (e) {
reject(e)
}
// 测试捕获功能
new MyPromise((resolve, reject) => {
// 故意打印一个未定义的值
console.log(a)
}).then(value => {
console.log(value)
}, error => {
// 将会触发失败的回调函数
console.log(error)
})
复制代码
这样就可以捕获错误并触发reject
了,但是如果Promise
使用异步触发resolve/reject
时,以上代码就无法正常触发then
中成功和失败的回调,所以需要利用发布订阅机制,事先保存好成功和失败的回调,然后在resolve/reject
触发的时候,再去触发回调
实现异步触发 resolve/reject
...
this.onResolvedCallback = [] // 保存 resolve 回调
this.onRejectedCallback = [] // 保存 reject 回调
// resolve 函数
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fullFilled'
this.value = value
this.onResolvedCallback.forEach(fn => fn())
}
}
// reject 函数
const reject = error => {
if (this.state === 'pending') {
this.state = 'rejected'
this.error = error
this.onRejectedCallback.forEach(fn => fn())
}
}
// then 方法
then(onFullFilled, onRejected) {
...
// 如果状态为 pending,说明 resolve 或 reject 当前为异步执行,需保存其回调,延后执行
if (this.state === 'pending') {
this.onResolvedCallback.push(() => {
onFullFilled(this.value)
})
this.onRejectedCallback.push(() => {
onRejected(this.error)
})
}
}
// 测试异步代码
new MyPromise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.5) {
resolve(10)
} else {
reject(-10)
}
}, 1000)
}).then(value => {
console.log(value)
}, error => {
console.log(error)
})
复制代码
这样在异步触发resolve/reject
的情况下,then
中的成功回调和失败回调也能成功触发,接下来,要实现then
的链式调用
实现 then
的链式调用
// then 方法
then(onFullFilled, onRejected) {
let x
return new MyPromise((resolve, reject) => {
// 如果状态为 fullFilled,执行 resolve 回调
if (this.state === 'fullFilled') {
x = onFullFilled(this.value)
resolve(x)
}
// 如果状态为 fullFilled,执行 reject 回调
if (this.state === 'rejected') {
x = onRejected(this.error)
resolve(x)
}
// 如果状态为 pending,说明 resolve 或 reject 当前为异步执行,需保存其回调,延后执行
if (this.state === 'pending') {
this.onResolvedCallback.push(() => {
x = onFullFilled(this.value)
resolve(x)
})
this.onRejectedCallback.push(() => {
x = onRejected(this.error)
resolve(x)
})
}
})
}
// 测试链式调用
const myPromise = new MyPromise((resolve, reject) => {
if (Math.random() < 0.5) {
resolve(10)
} else {
reject(-10)
}
})
myPromise.then(value => {
console.log('sucess:', value)
return value + 2
}, error => {
console.log('fail:', error)
return error - 2
}).then(value => {
console.log('sucess:', value)
return value + 8
}, error => {
console.log('fail:', error)
return error - 8
}).then(value => {
console.log('sucess:', value)
return value + 10
}, error => {
console.log('fail:', error)
return error - 10
})
复制代码
这样就实现了then
的链式调用,并且保证每个then
中成功和失败的回调都返回一个promise
对象,然后也要加上错误捕获机制
then
链式操作添加错误捕获
// then 方法
then(onFullFilled, onRejected) {
let x
return new MyPromise((resolve, reject) => {
// 如果状态为 fullFilled,执行 resolve 回调
if (this.state === 'fullFilled') {
// 添加错误捕获机制
try {
x = onFullFilled(this.value)
resolve(x)
} catch (e) {
reject(e)
}
}
// 如果状态为 fullFilled,执行 reject 回调
if (this.state === 'rejected') {
// 添加错误捕获机制
try {
x = onRejected(this.error)
resolve(x)
} catch (e) {
reject(e)
}
}
// 如果状态为 pending,说明 resolve 或 reject 当前为异步执行,需保存其回调,延后执行
if (this.state === 'pending') {
this.onResolvedCallback.push(() => {
// 添加错误捕获机制
try {
x = onFullFilled(this.value)
resolve(x)
} catch (e) {
reject(e)
}
})
this.onRejectedCallback.push(() => {
// 添加错误捕获机制
try {
x = onRejected(this.error)
resolve(x)
} catch (e) {
reject(e)
}
})
}
})
}
// 测试链式调用中错误捕获功能
const myPromise = new MyPromise((resolve, reject) => {
if (Math.random() < 0.5) {
resolve(10)
} else {
reject(-10)
}
})
myPromise.then(value => {
// 故意打印一个未定义的值
console.log(a)
return value + 2
}, error => {
// 故意打印一个未定义的值
console.log(a)
return error - 2
}).then(value => {
console.log('sucess:', value)
}, error => {
// 将会触发失败的回调函数
console.log('fail:', error)
})
复制代码
完整代码如下
class MyPromise {
constructor(executor) {
this.state = 'pending' // 状态
this.value = undefined // 保存 resolve 的值
this.error = undefined // 保存 reject 的值
this.onResolvedCallback = [] // 保存 resolve 回调
this.onRejectedCallback = [] // 保存 reject 回调
// resolve 函数
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fullFilled'
this.value = value
this.onResolvedCallback.forEach(fn => fn())
}
}
// reject 函数
const reject = error => {
if (this.state === 'pending') {
this.state = 'rejected'
this.error = error
this.onRejectedCallback.forEach(fn => fn())
}
}
try {
// 执行通过 new MyPromise() 传进来函数
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
// then 方法
then(onFullFilled, onRejected) {
let x
return new MyPromise((resolve, reject) => {
// 如果状态为 fullFilled,执行 resolve 回调
if (this.state === 'fullFilled') {
// 添加错误捕获机制
try {
x = onFullFilled(this.value)
resolve(x)
} catch (e) {
reject(e)
}
}
// 如果状态为 fullFilled,执行 reject 回调
if (this.state === 'rejected') {
// 添加错误捕获机制
try {
x = onRejected(this.error)
resolve(x)
} catch (e) {
reject(e)
}
}
// 如果状态为 pending,说明 resolve 或 reject 当前为异步执行,需保存其回调,延后执行
if (this.state === 'pending') {
this.onResolvedCallback.push(() => {
// 添加错误捕获机制
try {
x = onFullFilled(this.value)
resolve(x)
} catch (e) {
reject(e)
}
})
this.onRejectedCallback.push(() => {
// 添加错误捕获机制
try {
x = onRejected(this.error)
resolve(x)
} catch (e) {
reject(e)
}
})
}
})
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END