写在前面
笔记内容大多出自于拉勾教育大前端高薪训练营的教程,因此也许会和其他文章雷同较多,请担待。
Promise核心逻辑实现
- Promise就是一个类,在执行这个类的时候需要传递一个执行器出去,执行器会立即执行
- Promise有三种状态 -> pending fulfilled rejected
- Promise一旦状态改变,则不会再改变
- then方法内部就是判断状态,根据状态调用不同的回调
/* 简单版本-1 不支持异步情况 */
const PENDING = 'pending'
const FULFILLING = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
state = PENDING
value = undefined
reason = undefined
constructor(executor) {
executor(this.resolve, this.reject)
}
/* 箭头函数区域 start */
/* 这里箭头函数的作用是将函数体内的this指向当前类,因为在使用Promise的时候是直接resolve()/reject()的,所以这里的resolve/reject在没有箭头函数时是指向window的 */
resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLING
this.value = value
}
}
reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED
this.reason = reason
}
}
/* 箭头函数区域 end */
then(onFulfilledCallbacks, onRejectedCallbacks) {
// 判断状态
if (this.state === FULFILLING) {
onFulfilledCallbacks(this.value)
} else if (this.state === REJECTED) {
onRejectedCallbacks(this.reason)
}
}
}
new MyPromise((resolve, reject) => {
if (Math.random() > .5) {
resolve('success')
} else {
reject('fail')
}
}).then(
res => {
console.log('suc', res)
},
err => {
console.log('err', err)
}
)
/* 简单版本-2 支持异步情况 */
const PENDING = 'pending'
const FULFILLING = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
state = PENDING
value = undefined
reason = undefined
onFulfilledCallback = undefined
onRejectedCallback = undefined
constructor(executor) {
executor(this.resolve, this.reject)
}
/* 箭头函数区域 start */
/* 这里箭头函数的作用是将函数体内的this指向当前类,因为在使用Promise的时候是直接resolve()/reject()的,所以这里的resolve/reject在没有箭头函数时是指向window的 */
resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLING
this.value = value
this.onFulfilledCallback && this.onFulfilledCallback(this.value)
}
}
reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED
this.reason = reason
this.onRejectedCallback && this.onRejectedCallback(this.reason)
}
}
/* 箭头函数区域 end */
then(onFulfilledCallback, onRejectedCallback) {
// 判断状态
if (this.state === FULFILLING) {
onFulfilledCallback(this.value)
} else if (this.state === REJECTED) {
onRejectedCallback(this.reason)
} else {
this.onFulfilledCallback = onFulfilledCallback
this.onRejectedCallback = onRejectedCallback
}
}
}
new MyPromise((resolve, reject) => {
if (Math.random() > .5) {
setTimeout(() => {
resolve('success')
}, 2000)
} else {
setTimeout(() => {
reject('fail')
}, 2000)
}
}).then(
res => {
console.log('suc', res)
},
err => {
console.log('err', err)
}
)
/* 进阶版本 支持异步情况且支持多次then处理结果,但都是对第一个Promise对象传递出的结果进行处理 */
const PENDING = 'pending'
const FULFILLING = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
state = PENDING
value = undefined
reason = undefined
onFulfilledCallbacks = []
onRejectedCallbacks = []
constructor(executor) {
executor(this.resolve, this.reject)
}
/* 箭头函数区域 start */
/* 这里箭头函数的作用是将函数体内的this指向当前类,因为在使用Promise的时候是直接resolve()/reject()的,所以这里的resolve/reject在没有箭头函数时是指向window的 */
resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLING
this.value = value
while(this.onFulfilledCallbacks.length) this.onFulfilledCallbacks.shift()(this.value)
}
}
reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED
this.reason = reason
while(this.onRejectedCallbacks.length) this.onRejectedCallbacks.shift()(this.reason)
}
}
/* 箭头函数区域 end */
then(onFulfilledCallback, onRejectedCallback) {
// 判断状态
if (this.state === FULFILLING) {
onFulfilledCallback(this.value)
} else if (this.state === REJECTED) {
onRejectedCallback(this.reason)
} else {
this.onFulfilledCallbacks.push(onFulfilledCallback)
this.onRejectedCallbacks.push(onRejectedCallback)
}
}
}
const p = new MyPromise((resolve, reject) => {
if (Math.random() > .5) {
setTimeout(() => {
resolve('success')
}, 2000)
} else {
setTimeout(() => {
reject('fail')
}, 2000)
}
})
p.then(
res => {
console.log('suc-1', res)
},
err => {
console.log('err-1', err)
}
)
p.then(
res => {
console.log('suc-2', res)
},
err => {
console.log('err-2', err)
}
)
p.then(
res => {
console.log('suc-3', res)
},
err => {
console.log('err-3', err)
}
)
/* 进阶版本-2 支持多次then处理结果,并且每次then都是对前一个Promise对象传递出的结果进行处理,但在异步时会有问题 */
const PENDING = 'pending'
const FULFILLING = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
state = PENDING
value = undefined
reason = undefined
onFulfilledCallbacks = []
onRejectedCallbacks = []
constructor(executor) {
executor(this.resolve, this.reject)
}
/* 箭头函数区域 start */
/* 这里箭头函数的作用是将函数体内的this指向当前类,因为在使用Promise的时候是直接resolve()/reject()的,所以这里的resolve/reject在没有箭头函数时是指向window的 */
resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLING
this.value = value
while(this.onFulfilledCallbacks.length) this.onFulfilledCallbacks.shift()(this.value)
}
}
reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED
this.reason = reason
while(this.onRejectedCallbacks.length) this.onRejectedCallbacks.shift()(this.reason)
}
}
/* 箭头函数区域 end */
then(onFulfilledCallback, onRejectedCallback) {
return new MyPromise((resolve, reject) => {
// 判断状态
if (this.state === FULFILLING) {
resolve(onFulfilledCallback(this.value))
} else if (this.state === REJECTED) {
reject(onRejectedCallback(this.reason))
} else {
this.onFulfilledCallbacks.push(onFulfilledCallback)
this.onRejectedCallbacks.push(onRejectedCallback)
}
})
}
}
const p = new MyPromise((resolve, reject) => {
if (Math.random() > .5) {
setTimeout(() => {
resolve('success-1')
}, 2000)
} else {
setTimeout(() => {
reject('fail-1')
}, 2000)
}
}).then(
res => {
console.log('suc-1', res)
return 'success-2'
},
err => {
console.log('err-1', err)
return 'err-2'
}
).then(
res => {
console.log('suc-2', res)
return 'success-3'
},
err => {
console.log('err-2', err)
return 'success-3'
}
).then(
res => {
console.log('suc-3', res)
},
err => {
console.log('err-3', err)
}
)
/* 进阶版本-3 支持多次then处理结果,并且每次then都是对前一个Promise对象传递出的结果进行处理,且在异步时没有问题 */
const PENDING = 'pending'
const FULFILLING = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
state = PENDING
value = undefined
reason = undefined
onFulfilledCallbacks = []
onRejectedCallbacks = []
constructor(executor) {
try {
executor(this.resolve, this.reject)
} catch(e) {
this.reject(e)
}
}
/* 箭头函数区域 start */
/* 这里箭头函数的作用是将函数体内的this指向当前类,因为在使用Promise的时候是直接resolve()/reject()的,所以这里的resolve/reject在没有箭头函数时是指向window的 */
resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLING
this.value = value
while(this.onFulfilledCallbacks.length) this.onFulfilledCallbacks.shift()()
}
}
reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED
this.reason = reason
while(this.onRejectedCallbacks.length) this.onRejectedCallbacks.shift()()
}
}
/* 箭头函数区域 end */
then(onFulfilledCallback, onRejectedCallback) {
let promise2 = new MyPromise((resolve, reject) => {
onFulfilledCallback = onFulfilledCallback ? onFulfilledCallback : value => value
onRejectedCallback = onRejectedCallback ? onRejectedCallback : reason => { throw reason }
// 判断状态
if (this.state === FULFILLING) {
// 使用定时器是为了获取到promise2
setTimeout(() => {
try {
let result = onFulfilledCallback(this.value)
resolvePromise(promise2, result, resolve, reject)
} catch(e) {
reject(e)
}
})
} else if (this.state === REJECTED) {
// 使用定时器是为了获取到promise2
setTimeout(() => {
try {
let result = onRejectedCallback(this.reason)
resolvePromise(promise2, result, resolve, reject)
} catch(e) {
reject(e)
}
})
} else {
this.onFulfilledCallbacks.push(() => {
// 使用定时器是为了获取到promise2
setTimeout(() => {
try {
let result = onFulfilledCallback(this.value)
resolvePromise(promise2, result, resolve, reject)
} catch(e) {
reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
// 使用定时器是为了获取到promise2
setTimeout(() => {
try {
let result = onRejectedCallback(this.reason)
resolvePromise(promise2, result, resolve, reject)
} catch(e) {
reject(e)
}
})
})
}
})
return promise2
}
}
function resolvePromise(promise2, result, resolve, reject) {
// then中可能返回自身,所以需要做这一步判断阻止程序运行
if (promise2 === result) return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
if (result instanceof MyPromise) {
// Promise对象
result.then(
res => {
resolve(res)
},
err => {
reject(err)
}
)
} else {
// 普通值
resolve(result)
}
}
const p = new Promise((resolve, reject) => {
if (Math.random() > .5) {
setTimeout(() => {
resolve('success-1')
}, 2000)
} else {
setTimeout(() => {
reject('fail-1')
}, 2000)
}
}).then(
res => {
console.log('suc-1', res)
return 'success-2'
},
err => {
console.log('err-1', err)
return 'fail-2'
}
).then(
res => {
console.log('suc-2', res)
return 'success-3'
},
err => {
console.log('err-2', err)
return 'fail-3'
}
).then(
res => {
console.log('suc-3', res)
},
err => {
console.log('err-3', err)
}
)
/* 进阶版本-4 all方法、finally方法和catch方法 */
const PENDING = 'pending'
const FULFILLING = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
state = PENDING
value = undefined
reason = undefined
onFulfilledCallbacks = []
onRejectedCallbacks = []
constructor(executor) {
try {
executor(this.resolve, this.reject)
} catch(e) {
this.reject(e)
}
}
/* 箭头函数区域 start */
/* 这里箭头函数的作用是将函数体内的this指向当前类,因为在使用Promise的时候是直接resolve()/reject()的,所以这里的resolve/reject在没有箭头函数时是指向window的 */
resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLING
this.value = value
while(this.onFulfilledCallbacks.length) this.onFulfilledCallbacks.shift()()
}
}
reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED
this.reason = reason
while(this.onRejectedCallbacks.length) this.onRejectedCallbacks.shift()()
}
}
/* 箭头函数区域 end */
then(onFulfilledCallback, onRejectedCallback) {
let promise2 = new MyPromise((resolve, reject) => {
onFulfilledCallback = onFulfilledCallback ? onFulfilledCallback : value => value
onRejectedCallback = onRejectedCallback ? onRejectedCallback : reason => { throw reason }
// 判断状态
if (this.state === FULFILLING) {
// 使用定时器是为了获取到promise2
setTimeout(() => {
try {
let result = onFulfilledCallback(this.value)
resolvePromise(promise2, result, resolve, reject)
} catch(e) {
reject(e)
}
})
} else if (this.state === REJECTED) {
// 使用定时器是为了获取到promise2
setTimeout(() => {
try {
let result = onRejectedCallback(this.reason)
resolvePromise(promise2, result, resolve, reject)
} catch(e) {
reject(e)
}
})
} else {
this.onFulfilledCallbacks.push(() => {
// 使用定时器是为了获取到promise2
setTimeout(() => {
try {
let result = onFulfilledCallback(this.value)
resolvePromise(promise2, result, resolve, reject)
} catch(e) {
reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
// 使用定时器是为了获取到promise2
setTimeout(() => {
try {
let result = onRejectedCallback(this.reason)
resolvePromise(promise2, result, resolve, reject)
} catch(e) {
reject(e)
}
})
})
}
})
return promise2
}
finally(callback) {
return this.then(
value => {
return MyPromise.resolve(callback()).then(() => value)
},
reason => {
return MyPromise.resolve(callback()).then(() => { throw reason })
}
)
}
catch(onRejectedCallback) {
return this.then(undefined, onRejectedCallback)
}
static all(array) {
let result = []
let index = 0
return new MyPromise((resolve, reject) => {
function addData(key, value) {
result[key] = value
index++
if (index === array.length - 1) resolve(result)
}
for (let i = 0; i < array.length; i++) {
if (array[i] instanceof MyPromise) {
array[i].then(res => addData(i, res), err => reject(err))
} else {
addData(i, array[i])
}
}
})
}
static resolve(value) {
if (value instanceof MyPromise) {
return value
} else {
return new Promise(resolve => resolve(value))
}
}
}
function resolvePromise(promise2, result, resolve, reject) {
// then中可能返回自身,所以需要做这一步判断阻止程序运行
if (promise2 === result) return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
if (result instanceof MyPromise) {
// Promise对象
result.then(
res => {
resolve(res)
},
err => {
reject(err)
}
)
} else {
// 普通值
resolve(result)
}
}
const p = new Promise((resolve, reject) => {
if (Math.random() > .5) {
setTimeout(() => {
resolve('success-1')
}, 2000)
} else {
setTimeout(() => {
reject('fail-1')
}, 2000)
}
}).then(
res => {
console.log('suc-1', res)
return 'success-2'
},
err => {
console.log('err-1', err)
return 'fail-2'
}
).then(
res => {
console.log('suc-2', res)
return 'success-3'
},
err => {
console.log('err-2', err)
return 'fail-3'
}
).then(
res => {
console.log('suc-3', res)
},
err => {
console.log('err-3', err)
}
)