更新
最近看到一个实现,讲得更加清晰,于是重新实现了一遍
class GePromise {
constructor(fn) {
this.state = 'pending'
this.value = undefined
this.resolvedCb = []
this.rejectedCb = []
let self = this
try {
let resolve = self.__resolve.bind(self)
let reject = self.__reject.bind(self)
fn(resolve, reject)
} catch (e) {
self.__reject(e)
}
}
__resolve(value) {
let self = this
if (value instanceof GePromise) {
return value.then(self.__resolve, self.__reject)
}
setTimeout(() => {
self.state = 'resolved'
self.value = value
self.resolvedCb.forEach(cb => cb())
}, 0)
}
__reject(reason) {
let self = this
setTimeout(() => {
self.state = 'rejected'
self.value = reason
self.rejectedCb.forEach(cb => cb())
}, 0)
}
then(onResolved, onRejected) {
let self = this
let state = this.state
let newPromise
if (state === 'resolved') {
newPromise = new GePromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onResolved(self.value)
self.value = x
resolve(x)
} catch (reason) {
reject(reason)
}
}, 0)
})
} else if (state === 'rejected') {
newPromise = new GePromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(self.value)
self.value = x
resolve(x)
} catch (reason) {
reject(reason)
}
}, 0)
})
} else if (state === 'pending') {
newPromise = new GePromise((resolve, reject) => {
self.resolvedCb.push(() => {
try {
let x = onResolved(self.value)
self.value = x
resolve(x)
} catch (reason) {
reject(reason)
}
})
self.rejectedCb.push(() => {
try {
let x = onRejected(self.value)
self.value = x
resolve(x)
} catch (reason) {
reject(reason)
}
})
})
}
return newPromise
}
}
const simpleTest = () => {
let a = new GePromise((res, rej) => {
setTimeout(() => {
console.log('set timeout')
res('resolve')
}, 1000)
})
let b = a.then((res) => {
console.log(res) // resolve
return 'after resolve'
}, (rej) => {
console.error(rej)
return 'first reject'
}).then(res => {
console.log(res) // after resolve
})
}
原文
之前看到朋友实现了一个promise,觉得挺好玩的,心中跃跃欲试,于是近期看了一些文章,自己也跟着实现了一遍,记录下来。
promise是为了解决回调地狱,它是通过then方法来注册回调函数,使得代码在组织上更加清晰。
一个简单的雏形:
class GePromise {
constructor(fn) {
this.value = null
this.callbacks = []
this.init(fn)
}
init(fn) {
const self = this
const resolve = function(value) {
self.callbacks.forEach((callback) => {
callback(value)
})
}
fn(resolve)
}
then(fn) {
this.callbacks.push(fn)
return this
}
}
const test_1 = function () {
const p = new GePromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
console.log(2)
})
p.then((val) => {
console.log(val)
})
}
test_1()
这时候会有一个问题,有可能在then注册好回调之前,resolve就执行了,因此加入延时机制:
...
const resolve = function(value) {
setTimeout(() => {
self.callbacks.forEach((callback) => {
callback(value)
})
}, 0)
}
...
引入状态控制:
class GePromise {
constructor(fn) {
this.state = 'pending'
this.value = null
this.callbacks = []
this._init(fn)
}
_init(fn) {
const resolve = this._resolve.bind(this)
fn(resolve)
}
_resolve(value) {
const self = this
self.value = value
self.state = 'fulfilled'
setTimeout(() => {
self.callbacks.forEach((callback) => {
callback(value)
})
}, 0)
}
then(fn) {
if (this.state === 'pending') {
this.callbacks.push(fn)
} else {
const val = this.value
fn(val)
}
return this
}
}
const test = function () {
const p = new GePromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
console.log(2)
})
p.then((val) => {
console.log(val)
})
setTimeout(() => {
p.then((val) => {
console.log(3)
})
}, 3000)
}
test()
最后加入reject:
class GePromise {
constructor(fn) {
this.state = 'pending'
this.value = null
this.successCb = []
this.errorCb = []
this._init(fn)
}
_init(fn) {
const resolve = this._resolve.bind(this)
const reject = this._reject.bind(this)
fn(resolve, reject)
}
_resolve(value) {
const self = this
self.value = value
self.state = 'fulfilled'
setTimeout(() => {
self.successCb.forEach((callback) => {
callback(value)
})
}, 0)
}
_reject(reason) {
const self = this
self.value = reason
self.state = 'rejected'
setTimeout(() => {
self.errorCb.forEach((callback) => {
callback(reason)
})
}, 0)
}
then(fn) {
if (this.state === 'pending') {
this.successCb.push(fn)
} else {
const val = this.value
fn(val)
}
return this
}
catch(fn) {
if (this.state === 'pending') {
this.errorCb.push(fn)
} else {
const val = this.value
fn(val)
}
return this
}
}
网友评论