今天来玩一下Promise,一步步分析。
- 原版Promise效果
let promise = new Promise((resolve, reject) => resolve("success"));
promise.then(msg => console.log(msg));
复制代码

- 自定义一个Pomise
class MyPromise {
constructor(func) {
this.callbacks = []
// 绑定this指向
const resolve = this.resolve.bind(this)
func(resolve)
}
resolve(e) {
this.callbacks.forEach(cb => cb(e))
}
reject() {
console.error('reject')
}
then(cb) {
this.callbacks.push(cb)
}
}
new MyPromise((resolve, _) => setTimeout(() => resolve('success'), 0)).then(e => console.log(e))
复制代码
- 执行结果

- 此时看起来似乎实现了功能,但是当
new MyPromise的时候把异步方法变成同步方法,此时then方法里无法打印出值,如:
new MyPromise((resolve, _) => resolve('success')).then(e => console.log(e))
复制代码
- 此时应该想办法把
then方法里的函数放在resolve方法执行之前,所以采取浏览器事件触发线程,把事件添加到待处理JS任务队列的队尾,等待js引擎的处理,让resolve执行的时时候then方法的回调函数已经存在回调数组callbacks中,如setTimeout方法。这里就有人疑问了,不是刚去掉吗,怎么又加上哈哈。。。的确,但是加的位置不一样了,如:
class MyPromise {
constructor(func) {
this.callbacks = []
// 绑定this指向
const resolve = this.resolve.bind(this)
// 此处加上setTimeout方法
setTimeout(() => func(resolve), 0)
}
resolve(e) {
this.callbacks.forEach(cb => cb(e))
}
reject() {
console.error('reject')
}
then(cb) {
this.callbacks.push(cb)
}
}
new MyPromise((resolve, _) => resolve('success')).then(e => console.log(e))
复制代码
- 熟悉的结果回来了。要是执行中途出现异常,那就捕获异常并返回
reject,如:
try {
setTimeout(() => func(resolve), 0)
} catch (error) {
this.reject()
}
复制代码
- 接着有人问,这里只有一个
then方法,那么多个then方法怎么办呢?好办,链式调用,在then方法中return this,如:
then(cb) {
this.callbacks.push(cb)
// 链式调用
return this
}
复制代码
- 输出代码
new MyPromise((resolve, _) => resolve('success')).then(e => console.log(e)).then(e => console.log(e))
复制代码
- 执行结果

- 这样看着可以执行多个
then方法了,可是还有问题,细心的小伙伴发现了then方法执行后的结果每次都是一样的,并没有随着上次执行的变化而变化,如:

- 两次
then方法中取到的数据都是1。所以要把then方法返回的值保存一下
class MyPromise {
constructor(func) {
// 初始化值
this.value = null;
this.callbacks = []
// 绑定this指向
const resolve = this.resolve.bind(this)
setTimeout(() => func(resolve), 0)
}
resolve(e) {
this.value = e
this.callbacks.forEach(cb => {
let newValue = cb(this.value)
// 把then方法返回的值存起来
this.value = newValue
})
}
reject() {
console.error('reject')
}
then(cb) {
this.callbacks.push(cb)
return this
}
}
复制代码
- 执行结果

- 然后还有小伙伴说,当最后一次
then方法是个耗时好操作怎么办,只会输出一个数值,如:

- 这里遵循Promise源码的规定,在Promise源码中是有状态这一说的,有
三种状态,pending - 进行中、fulfilled - 成功、rejected - 失败。当主体执行完后,把状态变更一下,后续再执行直接把后续加上的then方式执行即可,所以实现一下,如:
// 状态对象
const stateObj = {
PENDING: 'pending',
FULFILLED: 'fulfilled',
REJECTED: 'rejected'
}
class MyPromise {
constructor(func) {
// 初始化状态
this.state = stateObj.PENDING
// 初始化值
this.value = null;
this.callbacks = []
// 绑定this指向
const resolve = this.resolve.bind(this)
try {
setTimeout(() => func(resolve), 0)
} catch (error) {
this.reject()
}
}
resolve(e) {
this.value = e
// 改变状态
this.state = stateObj.FULFILLED
this.callbacks.forEach(cb => {
let newValue = cb(this.value)
// 把then方法返回的值存起来
this.value = newValue
})
}
reject() {
console.error(stateObj.REJECTED)
}
then(cb) {
if (this.state === stateObj.PENDING) {
this.callbacks.push(cb)
return this
}
try {
// 后续调用直接执行传进来的方法
cb(this.value)
} catch (error) {
this.reject()
}
return this
}
}
const mp = new MyPromise((resolve, _) => resolve(2)).then(e => {
console.log(e)
return e * 2
})
setTimeout(() => {
mp.then(e => {
console.log(e)
return e * 2
})
}, 3000)
复制代码
- 执行结果又回来了

好咧,今天就玩到这里,后续继续优化
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END








![Family Connections ‘argv[1]’ 参数远程任意命令执行漏洞-一一网](https://www.proyy.com/skycj/data/images/2021-04-24/88b6f048d3a2ba9a61ae18104ca8d7d0.png)












![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)