要点:
- 它有3个状态,pending、fulfilled、rejected,一经改变不可逆转
- new Promise接受一个executor()执行器,并立即执行
- executor接受resolve和reject
- then方法,接受2个参数,成功执行参数1,onFulfilled,参数是成功的值value;失败执行参数2, onRejected,参数是失败的值reason;
- then链式调用,值的穿透
- catch、finally
- all,race,any,allsettled常用方法
基础结构
- 它有3个状态,pending、fulfilled、rejected,一经改变不可逆转
- new Promise接受一个executor()执行器,并立即执行
- executor接受resolve和reject
js
class myPromise {
constructor(executor) {
this.state = 'pending'
this.value = ''
this.reason = ''
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
}
}
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
}
}
try {
executor(resolve, reject)
}
catch (error) {
reject(error)
}
}
}
then方法
then方法,接受2个参数,成功执行参数1,onFulfilled,参数是成功的值value;失败执行参数2, onRejected,参数是失败的值reason;
js
class myPromise {
constructor(executor) {
this.state = 'pending'
this.value = ''
this.reason = ''
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
}
}
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
}
}
try {
executor(resolve, reject)
}
catch (error) {
reject(error)
}
}
then(onFulFilled, onRejected) {
if (this.state === 'fulfilled') {
onFulFilled(this.value)
}
if (this.state === 'rejected') {
onRejected(this.reason)
}
}
}
new myPromise((resolve, reject) => {
reject(1)
}).then((res) => {
console.log('res', res)
}, (err) => {
console.log('err', err)
})
截至目前只处理同步操作,如果在 executor()中传入一个异步操作的话就会失效:
js
new myPromise((resolve, reject) => {
setTimeout(() => { reject(1) }, 2000)
}).then((res) => {
console.log('res', res)
}, (err) => {
console.log('err', err)
})
异步任务
在执行then的时候,这个promise的状态还是pending,pending时候不会执行then的2个方法参数的任何一个,所以就没得反应。换句话说,promise只有执行了resolve或reject,状态改变了,才会执行then。所以如果当调用 then 方法时,当前状态是 pending,我们需要先将成功和失败的回调分别存放起来,在executor()的异步任务被执行时,触发 resolve 或 reject,依次调用成功或失败的回调。
js
class myPromise {
constructor(executor) {
this.state = 'pending'
this.value = ''
this.reason = ''
this.onFulFilledCallbacks = []
this.onRejectedCallBacks = []
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
this.onFulFilledCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.onRejectedCallBacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
}
catch (error) {
reject(error)
}
}
then(onFulFilled, onRejected) {
if (this.state === 'fulfilled') {
onFulFilled(this.value)
}
if (this.state === 'rejected') {
onRejected(this.reason)
}
if (this.state === 'pending') {
this.onFulFilledCallbacks.push(() => {
onFulFilled(this.value)
})
this.onRejectedCallBacks.push(() => {
onRejected(this.reason)
})
}
}
}
then链式调用和值的穿透
- 关键点1:then返回的是一个promise,
- 关键点2:上一次返回的值可以作为下一个then方法执行的参数
实现关键点1,即:
js
class myPromise {
constructor(executor) {
this.state = 'pending'
this.value = ''
this.reason = ''
this.onFulFilledCallbacks = []
this.onRejectedCallBacks = []
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
this.onFulFilledCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.onRejectedCallBacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
}
catch (error) {
reject(error)
}
}
then(onFulFilled, onRejected) {
let promise2 = new myPromise((resolve, reject) => {
})
return promise2
// if (this.state === "fulfilled") {
// onFulFilled(this.value)
// }
// if (this.state === "rejected") {
// onRejected(this.reason)
// }
// if (this.state === "pending") {
// this.onFulFilledCallbacks.push(() => {
// onFulFilled(this.value)
// })
// this.onRejectedCallBacks.push(() => {
// onRejected(this.reason)
// })
// }
}
}
而promise2内部需要实现之前的内容,同时由于promise 的回调是微任务(microtask),所以需要使用queueMicrotask,再将值传递下去,即:
js
class myPromise {
constructor(executor) {
this.state = 'pending'
this.value = ''
this.reason = ''
this.onFulFilledCallbacks = []
this.onRejectedCallBacks = []
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
this.onFulFilledCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.onRejectedCallBacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
}
catch (error) {
reject(error)
}
}
then(onFulFilled, onRejected) {
const that = this
let promise2 = new myPromise((resolve, reject) => {
if (that.state === 'fulfilled') {
// onFulFilled(that.value)
try {
queueMicrotask(() => {
const result = onFulFilled(that.value)
resolve(result)
})
}
catch (error) {
reject(error)
}
}
if (that.state === 'rejected') {
// onRejected(that.reason)
try {
queueMicrotask(() => {
const result = onRejected(that.reason)
reject(result)
})
}
catch (error) {
reject(error)
}
}
if (that.state === 'pending') {
that.onFulFilledCallbacks.push(() => {
try {
queueMicrotask(() => {
onFulFilled(that.value)
})
}
catch (error) {
reject(error)
}
})
that.onRejectedCallBacks.push(() => {
try {
queueMicrotask(() => {
onRejected(that.reason)
})
}
catch (error) {
reject(error)
}
})
}
})
return promise2
}
}
注意到
js
try {
queueMicrotask(() => {
onFulFilled(that.value)
})
}
catch (error) {
reject(error)
}
部分重复,优化为:
js
class myPromise {
constructor(executor) {
this.state = 'pending'
this.value = ''
this.reason = ''
this.onFulFilledCallbacks = []
this.onRejectedCallBacks = []
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
this.onFulFilledCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.onRejectedCallBacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
}
catch (error) {
reject(error)
}
}
then(onFulFilled, onRejected) {
const that = this
let promise2 = new myPromise((resolve, reject) => {
function creatFulfillMicroTask() {
try {
queueMicrotask(() => {
const result = onFulFilled(that.value)
resolve(result)
})
}
catch (error) {
reject(error)
}
}
function creatRejectMicroTask() {
try {
queueMicrotask(() => {
const result = onRejected(that.reason)
reject(result)
})
}
catch (error) {
reject(error)
}
}
if (that.state === 'fulfilled') {
creatFulfillMicroTask()
}
if (that.state === 'rejected') {
creatRejectMicroTask()
}
if (that.state === 'pending') {
that.onFulFilledCallbacks.push(creatFulfillMicroTask)
that.onRejectedCallBacks.push(creatRejectMicroTask)
}
})
return promise2
}
}
const p1 = new myPromise((resolve, reject) => {
reject(1)
}).then(
(res) => {
console.log('res', res)
return 'kif'
},
(err) => {
console.log('err', err)
return 'kif2'
}
)
p1.then((res) => {
console.log('res2', res)
}, (err) => {
console.log('err2', err)
})
console.log('p1', p1)
但是下面运行会出错:
js
new myPromise((resolve, reject) => {
resolve(1)
}).then().then((res) => {
console.log('res2', res)
}, (err) => {
console.log('err2', err)
})
即需要实现值穿透,then没做任何处理的时候,值会往下传,主要在then入口处做处理
js
onFulFilled = typeof onFulFilled === 'function'
? onFulFilled
: v => v
onRejected = typeof onRejected === 'function'
? onRejected
: (error) => {
throw error
}
textreject的方法空时不可以写 v=>v,不然永远都不会走catch,应该v=>{throw v}
全部:
js
function resolvePromise(promise, result, resolve, reject) {
resolve(result)
}
class myPromise {
constructor(executor) {
this.state = 'pending'
this.value = ''
this.reason = ''
this.onFulFilledCallbacks = []
this.onRejectedCallBacks = []
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
this.onFulFilledCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.onRejectedCallBacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
}
catch (error) {
reject(error)
}
}
then(onFulFilled, onRejected) {
onFulFilled = typeof onFulFilled === 'function'
? onFulFilled
: v => v
onRejected = typeof onRejected === 'function'
? onRejected
: (error) => {
throw error
}
const that = this
let promise2 = new myPromise((resolve, reject) => {
function creatFulfillMicroTask() {
try {
queueMicrotask(() => {
const result = onFulFilled(that.value)
resolve(result)
})
}
catch (error) {
reject(error)
}
}
function creatRejectMicroTask() {
try {
queueMicrotask(() => {
const result = onRejected(that.reason)
reject(result)
})
}
catch (error) {
reject(error)
}
}
if (that.state === 'fulfilled') {
// onFulFilled(that.value)
// try {
// queueMicrotask(() => {
// const result = onFulFilled(that.value);
// resolve(result)
// })
// } catch (error) {
// reject(error)
// }
creatFulfillMicroTask()
}
if (that.state === 'rejected') {
// onRejected(that.reason)
// try {
// queueMicrotask(() => {
// const result = onRejected(that.reason);
// reject(result);
// })
// } catch (error) {
// reject(error)
// }
creatRejectMicroTask()
}
if (that.state === 'pending') {
that.onFulFilledCallbacks.push(creatFulfillMicroTask)
that.onRejectedCallBacks.push(creatRejectMicroTask)
}
})
return promise2
}
}
const p1 = new myPromise((resolve, reject) => {
resolve(1)
}).then().then((res) => {
console.log('res2', res)
}, (err) => {
console.log('err2', err)
})
喜欢 0
评论区在赶来的路上...