带着问题寻找答案,实现源码也许会更加轻松
对于Promise当中的一些特性,我们需要了解并且掌握,今天我们来根据特性一步一步的实现我们的Promise源码,更好的理解并且掌握它
1、resolve reject 实现
//html
let p = new Promise((resolve, reject) => {
resolve('OK11');
resolve('OK');
//reject('rrr')
});
console.log(p)
//js
class Promise{
constructor(executor){
let _this = this
_this.PromiseState = 'pending' //用于保存状态
_this.PromiseResult = null //用于保存结果
let resolve = function(data){
_this.PromiseState = 'success'//没有使用箭头函数,this指向要改变
_this.PromiseResult = data
}
let reject = function(data){
_this.PromiseState = 'rejected'
_this.PromiseResult = data
}
executor(resolve,reject)
}
一开始对于
executor(resolve,reject)
这一段不太理解,可以理解为new Promise实例化的时候传入一个函数,放到construtor中进行执行,函数需要传入俩个参数,需要用resolve和reject两个函数当做参数,这里在传入的函数中调用resolve即调用constructor中的resolve
来看下控制台打印结果
2、只能改变一次状态
Promise中只能改变一次状态,所以每次改变状态前判断一下状态是否已经改变了,这个比较简单
//html
let p = new Promise((resolve, reject) => {
resolve('OK11');
resolve('OK');
});
//js
let resolve = function(data){
+ if(_this.PromiseState!='pending') return
...
}
let reject = function(data){
+ if(_this.PromiseState!='pending') return
...
}
现在只会执行一次resolve
3、抛出错误改变
Promise中如果没有改变状态而是抛出错误,需要将状态改变为reject,那么我们在executor执行的时候捕获一下错误,如果有错误,改变状态
let p = new Promise((resolve, reject) => {
- resolve('OK11');
- resolve('OK');
+ throw 'error'
});
class Promise{
constructor(executor){
+ try {
executor(resolve,reject)
+ } catch (error) {
+ reject(error)
+ }
+ }
4、then实现
当进入到then的时候
promise同步状态下
执行到then的时候状态是已经改变的,then中传入两个函数,我们根据状态的不同调用不同的函数,调用函数的时候有一个value值,
这个value是执行
resolve('OK')
的时候已经将ok保存到PromiseResult中,所以在then中输出value的时候,其实就是输出PromiseResult
//html
let p = new Promise((resolve, reject) => {
resolve('OK');
});
p.then(value => {
console.log(value)
}, reason=>{
console.warn(reason)
})
//js
+ then(onResolved,onRejected){
+ if(this.PromiseState=='success'){
+ onResolved(this.PromiseResult)
+ }
+ if(this.PromiseState=='rejected'){
+ onRejected(this.PromiseResult)
+ }
}
此时我们的OK已经打印出来
5.异步调用时候then中的问题
以下这段代码不会输出ok,因为在then执行的时候,由于事件循环,then调用的时候resolve还未调用,所以在then中
PromiseState
的状态仍然未pending,因此不会输出,所以我们需要加一个判断
let p = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('OK');
},100)
});
p.then(value => {
console.log(value)
}, reason=>{
console.warn(reason)
})
p.then(value => {
console.log(2222)
}, reason=>{
console.warn(reason)
})
对于then执行的时候状态仍未pending的状态,我们将回调存到回调列表中,
等待resolve调用
的时候再去执行所有回调,之所以用数组保存
,因为可能有多个then回调
constructor(executor){
+ _this.callbacks = []
let resolve = function(data){
+ _this.callbacks.forEach((item)=>{
+ item.onResolve(_this.PromiseResult)
+ })
}
let reject = function(data){
+ _this.callbacks.forEach((item)=>{
+ item.onReject(_this.PromiseResult)
+ })
}
then(onResolve,onReject){
+ if(this.PromiseState=='pending'){//处理resolved异步比then慢执行的时候
+ this.callbacks.push({onResolve,onReject})
+ }
}
实现promise的返回值
如果返回值是一个
非promise
对象,返回状态设置为成功, 如果返回值是一个异常,返回状态设置为失败
我们知道then中返回的也是一个Promise,所以我们给then中返回一个Promise,只需要在promise中做两件事情,执行回调,改变状态
如果返回值是一个promise,此时我们的promise已经有then方法了,我们直接用then方法来处理状态的改变即可,最后加上一层try的错误检验,reject的方法相同
let p = new Promise((resolve, reject) => {
resolve(1);
});
let res = p.then(value => {
return new Promise((resolve,reject)=>{
resolve(2)
})
}, reason=>{
console.warn(reason)
})
console.log(p)
console.log(res)
//js
then(onResolve,onReject){
if(this.PromiseState=='pending'){
this.callbacks.push({onResolve,onReject})
}
return new Promise((resolve,reject)=>{
if(this.PromiseState=='success'){
try {
let res = onResolve(this.PromiseResult)//执行回调
if(res instanceof Promise){
res.then((v)=>{//之所以加这一层 是因为promise状态改变了 但是里面的值没输出 所以要加个then,不然就成了promise里面包裹着一个pormise
resolve(v)//改变状态
},(r)=>{
reject(r)//改变状态
})
}else{
resolve(res)//改变状态
}
} catch (error) {
reject(error)
}
}
})
}
执行一下看看
let p = new Promise((resolve, reject) => {
resolve(1);
});
let res = p.then(value => {
return new Promise((resolve,reject)=>{
resolve(2)
})
}, reason=>{
console.warn(reason)
})
console.log(p)
console.log(res)
如果没有判断res instanceof Promise
,第二个then的会输出一个promise

加上判断后的结果

一开始我在判断返回值为promise这个地方一直搞不懂,为啥要执行then,为啥调用resolve,所以在写源码的时候应该多动手打印、debugger输出,下面是我对这段代码的解释
return new Promise((resolve,reject)=>{
...
if (result instanceof Promise) {//如果是 Promise 类型的对象
result.then(v => {
//之所以加这一层 是以为result是一个promise,
// 他的成功和失败决定了外层promise的状态(也就是真正then返回的promise)
//那么他成功 则调用外层的成功
resolve(v);
}, r => {
reject(r);
})
}
转载自:https://juejin.cn/post/7166511121308844068