我的思路是根据这个Promise的使用方法,一步步用js还原其原理
// 这个回调函数传进来就开始执行了
let oP = new Promise((resolve, reject) => {
resolve(1)
})
// 这个要根据你的状态进行选择 Fulfilled pending Rejected
oP.then((res) => {
console.log(res)
}, (rej)=> {
console.log(rej)
})
// 源码实现
// Fulfilled pending Rejected
function MyPromise(executor) {
let self = this
this.status = 'pending'
this.resolveValue = null
this.rejectValue = null
this.ResolveCallBackList = []
this.RejectCallBackList = []
function resolve(val) {
if(self.status === 'pending') {
self.status = 'Fulfilled'
self.resolveValue = val
}
}
function reject(reason) {
if(self.status === 'pending') {
self.status = 'Rejected'
self.rejectValue = reason
}
}
try {
executor(resolve, reject)
} catch(e) {
reject(e)
}
}
MyPromise.prototype.then = function(onFulfilled, onRejected) {
let self = this
if(this.status === 'Fulfilled') {
onFulfilled(self.resolveValue)
}
if(this.status === 'Rejected') {
onRejected(self.rejectValue)
}
}
现在有了初步的实现,我们继续完善功能,如果是出现如下情况
let oP = new MyPromise((resolve, reject) => {
// resolve函数放在了异步事件中,那么此时then函数会先于resolve执行
// then函数无法拿到resolve函数所传的值
setTimeout(() => {
resolve(1)
});
})
解决方法:构造函数定义一个回调列表,分别对应
Fulfilled Rejected 这个状态
// Fulfilled pending Rejected
function MyPromise(executor) {
let self = this
this.status = 'pending'
this.resolveValue = null
this.rejectValue = null
this.ResolveCallBackList = []
this.RejectCallBackList = []
function resolve(val) {
if (self.status === 'pending') {
self.status = 'Fulfilled'
self.resolveValue = val
self.ResolveCallBackList.forEach(item => {
item()
})
}
}
function reject(reason) {
if (self.status === 'pending') {
self.status = 'Rejected'
self.rejectValue = reason
self.RejectCallBackList.forEach(item => {
item()
})
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
MyPromise.prototype.then = function (onFulfilled, onRejected) {
let self = this
if (this.status === 'Fulfilled') {
onFulfilled(self.resolveValue)
}
if (this.status === 'Rejected') {
onRejected(self.rejectValue)
}
if (this.status === 'pending') {
self.ResolveCallBackList.push(function () {
onFulfilled(self.resolveValue)
})
self.RejectCallBackList.push(function () {
onRejected(self.rejectValue)
})
}
}
继续添加功能:
功能1:由于then函数是一个微任务事件,这里我们使用setTimeout进行模拟
功能2:实现then函数的一个链式调用
功能3:then函数中出异常,利用try、catch进行处理
功能四:如果是then函数传入的参数出现空值,那么需要对参数进行非空判断并且进行重写
// Fulfilled pending Rejected
function MyPromise(executor) {
let self = this
this.status = 'pending'
this.resolveValue = null
this.rejectValue = null
this.ResolveCallBackList = []
this.RejectCallBackList = []
function resolve(val) {
if (self.status === 'pending') {
self.status = 'Fulfilled'
self.resolveValue = val
self.ResolveCallBackList.forEach(item => {
item()
})
}
}
function reject(reason) {
if (self.status === 'pending') {
self.status = 'Rejected'
self.rejectValue = reason
self.RejectCallBackList.forEach(item => {
item()
})
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
MyPromise.prototype.then = function (onFulfilled, onRejected) {
if(!onFulfilled) {
onFulfilled = function(val) {
return val
}
}
if(!onRejected) {
onRejected = function(reason) {
return reason
}
}
let self = this
let nextPromise = new MyPromise(function (res, rej) {
if (self.status === 'Fulfilled') {
setTimeout(() => {
try {
let returnValue = onFulfilled(self.resolveValue)
res(returnValue)
} catch (e) {
rej(e)
}
})
}
if (self.status === 'Rejected') {
setTimeout(() => {
try {
let returnValue = onRejected(self.rejectValue)
rej(returnValue)
} catch (e) {
rej(e)
}
})
}
if (self.status === 'pending') {
self.ResolveCallBackList.push(function () {
setTimeout(() => {
try {
let returnValue = onFulfilled(self.resolveValue)
res(returnValue)
} catch (e) {
rej(e)
}
})
})
self.RejectCallBackList.push(function () {
setTimeout(() => {
try {
let returnValue = onRejected(self.rejectValue)
rej(returnValue)
} catch (e) {
rej(e)
}
})
})
}
})
return nextPromise
}
最后一个功能:then函数中的参数(参数是个函数)返回的是一个MyPromise对象,我们应该如何处理。案例如下:
let oP = new Promise((resolve, reject) => {
resolve(1)
})
// 这里有两个promise之间的关系问题,实际上也是我们需要解决的问题
oP.then((res) => {
console.log(res)
return new Promise((res, rej) => {
res(1) // 这个返回来的Promise对象最后赋值给then函数的内部变量
})
}).then(res => {
console.log('then: ', res)
})
解决方法:
// Fulfilled pending Rejected
function MyPromise(executor) {
let self = this
this.status = 'pending'
this.resolveValue = null
this.rejectValue = null
this.ResolveCallBackList = []
this.RejectCallBackList = []
function resolve(val) {
if (self.status === 'pending') {
self.status = 'Fulfilled'
self.resolveValue = val
self.ResolveCallBackList.forEach(item => {
item()
})
}
}
function reject(reason) {
if (self.status === 'pending') {
self.status = 'Rejected'
self.rejectValue = reason
self.RejectCallBackList.forEach(item => {
item()
})
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
function ResolutionReturnPromise(returnValue, res, rej) {
if(returnValue instanceof MyPromise) {
returnValue.then((val) => {
res(val)
}, (reason) => {
rej(reason)
})
} else {
res(returnValue)
}
}
MyPromise.prototype.then = function (onFulfilled, onRejected) {
if(!onFulfilled) {
onFulfilled = function(val) {
return val
}
}
if(!onRejected) {
onRejected = function(reason) {
return reason
}
}
let self = this
let nextPromise = new MyPromise(function (res, rej) {
if (self.status === 'Fulfilled') {
setTimeout(() => {
try {
let returnValue = onFulfilled(self.resolveValue)
ResolutionReturnPromise(returnValue, res, rej)
} catch (e) {
rej(e)
}
})
}
if (self.status === 'Rejected') {
setTimeout(() => {
try {
let returnValue = onRejected(self.rejectValue)
ResolutionReturnPromise(returnValue, res, rej)
} catch (e) {
rej(e)
}
})
}
if (self.status === 'pending') {
self.ResolveCallBackList.push(function () {
setTimeout(() => {
try {
let returnValue = onFulfilled(self.resolveValue)
ResolutionReturnPromise(returnValue, res, rej)
} catch (e) {
rej(e)
}
})
})
self.RejectCallBackList.push(function () {
setTimeout(() => {
try {
let returnValue = onRejected(self.rejectValue)
ResolutionReturnPromise(returnValue, res, rej)
} catch (e) {
rej(e)
}
})
})
}
})
return nextPromise
}
这里是个初稿,太困了,后续再附上详细说明和修正