一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情
🎉前言
Promise 不管是日常开发还是面试中,都是大家经常碰到的,所以掌握它是很有必要的,了解它的原理就能在遇到问题时能够更快的定位哦。
🎅 基础实现
原生的 Promise 代码:
let a = new Promise((resolve,reject) => {
resolve('成功')
reject('失败')
})
console.log('a', a);
let b = new Promise((resolve,reject) => {
reject('失败')
})
console.log('b', b);
let c = new Promise((resolve,reject) => {
throw('失败')
})
console.log('c', c);
打印结果为:
上述结果可以总结出四个知识:
- 执行
resolve时,PromiseState会变成fulfilled。 - 执行
reject时,PromiseState会变成rejected。 - 在
a代码代码块中,即执行resolve又执行reject,PromiseState以第一次为准,即一旦状态改变便不会在变。 - 执行
throw时,PromiseState会变成rejected。
那么我们只要实现这四个条件,就能有一个最基础版的 Promise 了。
手动实现 Promise 代码:
Promise 的初始状态为 pending。
这里很重要的一步是resolve和reject的绑定this,为什么要绑定this呢?这是为了resolve和reject的this指向永远指向当前的MyPromise实例,防止随着函数执行环境的改变而改变。
class MyPromise {
constructor (executor) {
// 初始化值
this.initValue();
// 初始化this指向
this.initBind();
// 立即执行两个函数
executor(this.resolve, this.reject);
}
initValue () {
// promise状态默认为 pending
this.PromiseState = 'pending';
// Result用来存放最后的结果
this.PromiseResult = null;
}
initBind () {
// 初始化this指向
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
}
resolve (value) {
// 执行 resolve 时,状态变为 fulfilled
this.PromiseState = 'fulfilled';
// 结果为传进来的值
this.PromiseResult = value;
}
reject (reson) {
// 执行 resolve 时,状态变为rejected
this.PromiseState = 'rejected';
// 结果为传进来的值
this.PromiseResult = reson;
}
}
测试代码:
let test1 = new MyPromise((resolve,reject) => {
resolve('成功')
})
let test2 = new MyPromise((resolve,reject) => {
reject('失败')
})
console.log('test1', test1);
console.log('test2', test2);
测试上述总结第三点,PromiseState 以第一次为准,即一旦状态改变便不会在变。
let test3 = new MyPromise((resolve,reject) => {
resolve('成功')
reject('失败')
})
console.log('test3', test3);
厚礼蟹,按照总结,状态应该以第一次为准,也就是 成功 和 fulfilled 才对。
OK,那我们修改一下代码:
resolve (value) {
+ // 如果 状态被改变(不等于pending)时,就返回,下面就不执行了
+ if (this.PromiseState !== 'pending') return;
// 执行 resolve 时,状态变为 fulfilled
this.PromiseState = 'fulfilled';
// 结果为传进来的值
this.PromiseResult = value;
}
reject (reson) {
+ // 如果 状态被改变(不等于pending)时,就返回,下面就不执行了
+ if (this.PromiseState !== 'pending') return;
// 执行 resolve 时,状态变为rejected
this.PromiseState = 'rejected';
// 结果为传进来的值
this.PromiseResult = reson;
}
再次测试结果:
let test3 = new MyPromise((resolve,reject) => {
resolve('成功')
reject('失败')
})
console.log('test3', test3);
nice! 成功了。
测试上述总结第四点,执行 throw 时,PromiseState 会变成 rejected。
在 Promise 中,如果有 throw 的话,就会执行 reject 。我们可以利用 try catch 包裹一下。
// 立即执行两个函数
try {
executor(this.resolve, this.reject);
} catch (e) {
// 如果错误就执行 reject
this.reject(e)
}
测试代码:
let test4 = new MyPromise((resolve,reject) => {
throw('失败')
})
console.log('test4', test4);
🎃 then 实现
then 方法是 Promise 的回调函数,它接收两个参数,一个 成功回调,一个 失败回调。
手动实现 then 方法:
then (onFulfilled, onRejected) {
// 校验两个参数是否是函数,这里使用 typeof
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : reson => { throw reson };
// 如果状态为 fulfilled 就执行 onFulfilled
if (this.PromiseState === 'fulfilled') {
onFulfilled(this.PromiseResult);
// 否则如果状态为 rejected 就执行 onRejected
} else if (this.onRejected === 'rejected') {
onRejected(this.PromiseResult);
}
}
测试代码:
let test5 = new MyPromise((resolve,reject) => {
resolve('成功啦,兄嘚!!')
}).then(res => {
console.log(res); // 成功啦,兄嘚!!
}, err => {
console.log(err);
})
OK,又实现了一个功能~~
👻 延迟调用
先测试一下如果在代码中加入 定时器(延迟) 效果,会发生什么?
let test5 = new MyPromise((resolve,reject) => {
setTimeout(() => {
resolve('成功啦,兄嘚!!')
});
}).then(res => {
console.log(res); // ???
}, err => {
console.log(err);
})
what? 半年没打印出东西...
因为上面的代码 then 方法是在 executor 立即执行函数执行时就调用了,这时候定时器里面的异步操作可能还没结束呢?也就是说 PromiseState 状态还是 pending ,既然是 pendng 肯定不能立即调onFulfilled或者onRejected的啦。
那什么时候知道 定时器里的结果是成功还是失败呢?我们应该将 onFulfilled 和 onRejected 两个回调保存起来,等到 定时器 里的结果执行后,在执行 resolve 或者 reject 方法调用对应的函数。
因为后面可能还有链式调用,按道理应该用 数组 保存起来,但是我们这里先用一个变量来保存,等实现链式调用后我们再稍作修改。
// 初始化值
initValue () {
//...省略代码
// 把回调结果保存起来
+ this.onFulfilled = null;
+ this.onRejected = null;
}
resolve (value) {
//...省略代码
+ // 执行保存的函数
+ this.onFulfilled(value);
}
reject (reson) {
//...省略代码
+ // 执行保存的函数
+ this.onRejected(reson);
}
then (onFulfilled, onRejected) {
//...省略代码
// 如果状态为 fulfilled 就执行 onFulfilled
if (this.PromiseState === 'fulfilled') {
onFulfilled(this.PromiseResult);
// 否则如果状态为 rejected 就执行 onRejected
} else if (this.onRejected === 'rejected') {
onRejected(this.PromiseResult);
+ } else {
+ // 否则 就是 pending 状态,保存两个回调函数
+ this.onFulfilled = onFulfilled;
+ this.onRejected = onRejected;
+ }
}
测试代码:
let test5 = new MyPromise((resolve,reject) => {
setTimeout(() => {
resolve('成功啦,兄嘚!!')
}, 1000);
}).then(res => {
console.log('res:', res); // 1秒后,打印 成功啦,兄嘚!!
}, err => {
console.log(err);
})
成功实现啦~~
✨总结
上面讲述的 Promise 原理功能实现还没完结,应该还有 链式调用 、all 、race 、allSettled 、any 等功能,这些我放到第二期在讲述,大家可以先把上述例子多写几遍,加深印象。有能力者,可以把剩下的功能自己实现一下哦~~
以上就是本次分享的全部内容~~
如果觉得文章写得不错,对你有所启发的,请不要吝啬 点个 赞 和 关注 并在 评论区 留下你宝贵的意见哦~~😃