1. 构造器的实现
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
#state = PENDING
#result = undefined
#changeState(state, result) {
if (this.#state !== PENDING) return
this.#state = state
this.#result = result
console.log(this.#state, this.#result)
}
constructor(exectutor) {
const resolve = (data) => {
this.#changeState(FULFILLED, data)
}
const reject = (reason) => {
this.#changeState(REJECTED, reason)
}
try {
exectutor(resolve, reject)
} catch (err) {
reject(err)
}
}
}
const p = new MyPromise((resolve, reject) => {
throw 123
})
console.log(p)
2. then的回调执行时机
添加then
函数基本结构返回结果仍然是promise 。
但是注意如果是异步执行resolve
或者reject
。则promise
的状态永远是pending
,而then
函数已经执行过,永远不会被再次执行
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.#state === FULFILLED) {
onFulfilled(this.#result)
}
if (this.#state === REJECTED) {
onRejected(this.#result)
}
})
const p = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
// resolve(1)
})
p.then((res) => {
console.log('promise 完成', res)
}, (err) => {
console.log('promise 失败', err)
})
改造then
函数 ,记录onFulfilled
,onRejected
,resolve
,reject
四个变量。等到promise
状态改变时再调用回调
将处理逻辑放入run
方法中,then
可以调用run
方法, changeState
也可以调用run
方法
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
#state = PENDING
#result = undefined
#handlers = []
#changeState(state, result) {
// 如果状态已经改变则返回。promise一旦确定状态就不会再改变
if (this.#state !== PENDING) return
this.#state = state
this.#result = result
this.#run()
}
#run() {
// 如果状态挂起,先不执行代码
if (this.#state === PENDING) return
while (this.#handlers.length) {
const {
onFulfilled,
onRejected,
resolve,
reject
} = this.#handlers.shift()
if (this.#state === FULFILLED) {
if (typeof onFulfilled === 'function') {
onFulfilled(this.#result)
}
} else {
if (this.#state === REJECTED) {
if (typeof onRejected === 'function') {
onRejected(this.#result)
}
}
}
}
}
constructor(exectutor) {
const resolve = (data) => {
this.#changeState(FULFILLED, data)
}
const reject = (reason) => {
this.#changeState(REJECTED, reason)
}
try {
exectutor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this.#handlers.push({
onFulfilled,
onRejected,
resolve,
reject
})
this.#run()
})
}
}
const p = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(1)
}, 1000)
// resolve(1)
})
p.then((res) => {
console.log('promise 完成1', res)
}, (err) => {
console.log('promise 失败1', err)
})
p.then((res) => {
console.log('promise 完成2', res)
}, (err) => {
console.log('promise 失败2', err)
})
p.then((res) => {
console.log('promise 完成3', res)
}, (err) => {
console.log('promise 失败3', err)
})
p.then((res) => {
console.log('promise 完成4', res)
}, (err) => {
console.log('promise 失败4', err)
})
3. then的返回值
-
如果对应的回调不是函数 ,即发生穿透。值穿透指的是,链式调用的参数不是函数时,会发生值穿透,就传入的非函数值忽略,传入的是之前的函数参数。
Promise.resolve(1) .then(null) .then((data) => { console.log( data) }) //1 Promise.resolve(1) .then(2) .then(Promise.resolve(3)) .then((data) => { console.log( data) }) // 1 #run() { // 如果状态挂起,先不执行代码 if (this.#state === PENDING) return while (this.#handlers.length) { const { onFulfilled, onRejected, resolve, reject } = this.#handlers.shift() if (this.#state === FULFILLED) { if (typeof onFulfilled === 'function') { onFulfilled(this.#result) } else { resolve(this.#result) } } else { if (this.#state === REJECTED) { if (typeof onRejected === 'function') { onRejected(this.#result) } else { reject(this.#result) } } } } }
-
如果对应的回调是函数,尝试运行函数并拿到返回结果
#run() { // 如果状态挂起,先不执行代码 if (this.#state === PENDING) return while (this.#handlers.length) { const { onFulfilled, onRejected, resolve, reject } = this.#handlers.shift() if (this.#state === FULFILLED) { if (typeof onFulfilled === 'function') { try { const data = onFulfilled(this.#result) resolve(data) } catch (err) { reject(err) } } else { resolve(this.#result) } } else { if (this.#state === REJECTED) { if (typeof onRejected === 'function') { try { const data = onRejected(this.#result) resolve(data) } catch (err) { reject(err) } } else { reject(this.#result) } } } } }
-
优化重复代码#runOne
#runOne(callback, resolve, reject) { if (typeof callback !== 'function') { const settled = this.#state === FULFILLED ? resolve : reject; settled(this.#result) } else { try { const result = callback(this.#result) resolve(result) } catch (err) { reject(err) } } } #run() { // 如果状态挂起,先不执行代码 if (this.#state === PENDING) return while (this.#handlers.length) { const { onFulfilled, onRejected, resolve, reject } = this.#handlers.shift() if (this.#state === FULFILLED) { this.#runOne(onFulfilled, resolve, reject) } else { this.#runOne(onRejected, resolve, reject) } } }
-
如果回调函数返回的结果是
promise
,首先需要辅助函数判断回调函数的结果是否是promise
。判断then
属性是否是函数#isPromiseLike(value) { if (value !== null && (typeof value === 'object' || typeof value === 'function')) { return typeof value.then === 'function' } return false } #runOne(callback, resolve, reject) { if (typeof callback !== 'function') { const settled = this.#state === FULFILLED ? resolve : reject; settled(this.#result) return } else { try { const data = callback(this.#result) if (this.#isPromiseLike(data)) { data.then(resolve, reject) } else { resolve(data) } } catch (err) { reject(err) } } }
4.微队列和PromiseLike
#runMicroTask(func) {
if (typeof process === "object" && typeof process.nextTick === "function") {
process.nextTick(func);
} else if (typeof MutationObserver === "function") {
const ob = new MutationObserver(func)
const textNode = document.createTextNode('1')
ob.observe(textNode, {
characterData: true
})
textNode.data = '2'
} else {
setTimeout(func, 0)
}
}
#runOne(callback, resolve, reject) {
this.#runMicroTask(() => {
if (typeof callback !== 'function') {
const settled = this.#state === FULFILLED ? resolve : reject;
settled(this.#result)
return
} else {
try {
const data = callback(this.#result)
if (this.#isPromiseLike(data)) {
data.then(resolve, reject)
} else {
resolve(data)
}
} catch (err) {
reject(err)
}
}
})
}
5. resolve和reject
catch(onRejected) {
return this.then(undefined, onRejected)
}
finally(onFinally) {
return this.then(data => {
onFinally();
return data
}, err => {
onFinally()
throw err
})
}
/*
1. 判断value是否是promise 如果是直接返回
2. 判断是否是then方法的promise如果是直接调用then方法
*/
static resolve(value) {
if (value instanceof MyPromise) {
return value
}
let _resolve, _reject
const p = new MyPromise((resolve, reject) => {
_resolve = resolve
_reject = reject
})
if (p.#isPromiseLike(value)) {
value.then(_resolve, _reject)
} else {
_resolve(value)
}
return p
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
6. promise.all
-
是静态方法返回一个promise
-
Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。
-
如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。
static all() {
let _resolve, _reject
const p = new MyPromise((resolve, reject) => {
_resolve = resolve
_reject = reject
})
let count = 0
for (let param of params) {
count++
}
// 空的迭代对象
if (count === 0) {
_resolve(result)
}
return p
}
static all(params) {
let _resolve, _reject
const p = new MyPromise((resolve, reject) => {
_resolve = resolve
_reject = reject
})
let count = 0
let fulfilledCount = 0
const result = []
for (let param of params) {
let i = count
count++
MyPromise.resolve(param).then(data => {
result[i] = data
fulfilledCount++
if (fulfilledCount === count) {
_resolve(result)
}
}, _reject)
}
// 空的迭代对象
if (count === 0) {
_resolve(result)
}
return p
}
测试
MyPromise.all([]).then(data => {
console.log(data) //[]
})
MyPromise.all([1, 2, 3, 4]).then(data => {
console.log(data) //[1, 2, 3, 4]
})
MyPromise.all([1, 2, 3, MyPromise.reject(4)]).then(data => {
console.log(data)
}, (err) => {
console.log(err) //4
})
MyPromise.all([1, 2, MyPromise.reject(3), MyPromise.reject(4)]).then(data => {
console.log(data)
}, (err) => {
console.log(err) //3
})
7. promise.race
static race(params) {
let _resolve, _reject
const p = new MyPromise((resolve, reject) => {
_resolve = resolve
_reject = reject
})
let result = null
for (let param of params) {
MyPromise.resolve(param).then(data => {
result = data
_resolve(result)
}, err => {
_reject(err)
})
}
return p
}
测试
const p = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
})
MyPromise.race([p, MyPromise.reject(3)]).then(data => {
console.log(data)
}, (err) => {
console.log(err) //3
})