1.Promise的基本用法
传统的异步处理的方式通常是通过回调函数去实现的,或者发布订阅 方式的事件监听。但是Promise出现之后就能够方便的进行异步处理。
先看Promise的基本用法:
const fn = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
},1000)
})
fn.then((res) => {
console.log(res)
})
在实例化Promise的时候,传进去了一个函数,这个函数有两个参数resolve和reject,它们是可执行函数,能够在then方法中去获取到resolve和reject执行时传入的参数。
2.初始化
首先写一个类,执行传入的函数executor,初始化状态为pending
class MyPromise {
constructor(executor){
this.initValue()
executor(this.resolve, this.reject)
}
initValue(){
this.PromiseState = 'pending'
this.PrimiseResult = null
}
resolve(value){
if(this.PromiseState !== 'pending') return
this.PromiseState = "fulfilled"
this.PromiseResult = value
}
reject(value){
if(this.PromiseState !== 'pending') return
this.PromiseState = 'rejected'
this.PromiseResult = value
}
}
接下来尝试去执行代码:
const fn = new MyPromise((resolve, reject) => {
resolve(1)
})
console.log(fn)
会发现报错了。Uncaught TypeError: Cannot read properties of undefined (reading 'PromiseState')
,执行到resolve的时候,this为undefind。所以在初始化的时候要绑定一下this的指向
class MyPromise {
constructor(executor){
this.initValue()
this.initBind()
executor(this.resolve, this.reject)
}
initValue(){
this.PromiseState = 'pending'
this.PromiseState = null
}
initBind(){
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
}
resolve(value){
console.log(this)
if(this.PromiseState !== 'pending') return
this.PromiseState = "fulfilled"
this.PromiseResult = value
}
reject(reason){
if(this.PromiseState !== 'pending') return
this.PromiseState = 'rejected'
this.PromiseResult = reason
}
}
在执行的过程中如果遇到了throw的情况时
const fn = new Promise((resolve, reject) => {
throw("出错啦")
})
console.log(fn)
promise要捕获该异常,执行返回错误原因,状态要变更为rejected,所以就可以通过
try catch
实现代码实现如下
constructor(executor){
this.initValue()
this.initBind()
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
3. then
3.1 实现then的基本操作
const fn = new Promise((resolve, reject) => {
//resolve(1)
//reject(2)
})
fn.then(res => {
console.log(res)
},err => {
console.log(err)
})
console.log(fn)
它有两个参数,都为函数,它们的参数就是reject和resolve的返回结果。代码实现如下
class MyPromise {
...
// 根据状态来决定执行哪个函数
then(onFulfilled,onRejected){
// 参数校验,确保一定是函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
if(this.PromiseState === 'fulfilled'){
onFulfilled(this.PromiseState)
}else if(this.PromiseState === 'rejected'){
onRejected(this.onRejected)
}
}
}
定时器的情况
const fn = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
},1000)
})
fn.then(res => {
console.log(res)
},err => {
console.log(err)
})
如果执行上面的代码,会发现then中是不会打印的,原因就是 PromiseState仍然是pending,要间隔1秒它的状态才会变化。 解决办法:当状态为pending时,将onFulfilled,onRejected存起来。当 状态变为 fulfilled或rejected时才去执行
class MyPromise {
...
initValue(){
this.PromiseState = 'pending'
this.PromiseResult = null
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
}
resolve(value){
...
while(this.onFulfilledCallbacks.length){
this.onFulfilledCallbacks.shift()(this.PromiseResult)
}
}
reject(reason){
...
while(this.onFulfilledCallbacks.length){
this.onRejectedCallbacks.shift()(this.PromiseResult)
}
}
then(onFulfilled,onRejected){
...
if(this.PromiseState === 'fulfilled'){
onFulfilled(this.PromiseResult)
}else if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult)
}else if(this.PromiseState === 'pending'){
this.onFulfilledCallbacks.push(onFulfilled)
this.onRejectedCallbacks.push(onRejected)
}
}
}
3.2 链式调用
要实现链式调用,那么then方法必然需要继续返回一个promise才可以。
then(onFulfilled,onRejected){
// 参数校验,确保一定是函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
const thenPromise = new MyPromise((resolve,reject) => {
if(this.PromiseState === 'fulfilled'){
onFulfilled(this.PromiseResult)
}else if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult)
}else if(this.PromiseState === 'pending'){
this.onFulfilledCallbacks.push(onFulfilled)
this.onRejectedCallbacks.push(onRejected)
}
})
return thenPromise
}
const fn = new MyPromise((resolve, reject) => {
resolve(1)
})
fn.then(res => {
console.log(res)
return res
},err => {
console.log(err)
}).then(res1 => {
console.log(res1)
})
这样虽然返回了一个promise,但是并没有去执行resolve,所以第二个res1 并没有被打印,所以要去执行resolve
then(onFulfilled,onRejected){
debugger
// 参数校验,确保一定是函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
const thenPromise = new MyPromise((resolve,reject) => {
if(this.PromiseState === 'fulfilled'){
resolve(onFulfilled(this.PromiseResult))
}else if(this.PromiseState === 'rejected'){
reject(onRejected(this.PromiseResult))
}else if(this.PromiseState === 'pending'){
this.onFulfilledCallbacks.push(onFulfilled)
this.onRejectedCallbacks.push(onRejected)
}
})
return thenPromise
}
这样就能就能打印两次1了。 看着好像没问题了,但是如果上一次的then方法继续返回的是一个promise对象,代码如下
const fn1 = new Promise((resolve, reject) => {
resolve(1)
})
fn.then(res => {
console.log(res)
return new Promise((resolve,reject) => {
resolve(res)
})
},err => {
console.log(err)
}).then(res1 => {
console.log(res1)
})
它打印出了1,所以上一次返回的是一个promise要主动的去执行then方法,所以改造自己的方法
then(onFulfilled,onRejected){
// 参数校验,确保一定是函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
const resolvePromise = (cb) => {
let x = cb(this.PromiseResult)
if(x instanceof MyPromise){
x.then(resolve, reject)
}else{
resolve(x)
}
}
const thenPromise = new MyPromise((resolve,reject) => {
if(this.PromiseState === 'fulfilled'){
resolvePromise(onFulfilled)
}else if(this.PromiseState === 'rejected'){
resolvePromise(onRejected)
}else if(this.PromiseState === 'pending'){
this.onFulfilledCallbacks.push.bind(this,onFulfilled)
this.onRejectedCallbacks.push.bind(this,onRejected)
}
})
return thenPromise
}
这里要注意this 的指向问题
另外如果上一个then 方法出错,那么需要通过try catch 去捕获异常,并直接 reject
const thenPromise = new MyPromise((resolve,reject) => {
const resolvePromise = (cb) => {
// setTimeout(() => {
try {
console.log(this)
let x = cb(this.PromiseResult)
if(x instanceof MyPromise){
// x.then(value => resolve(value),err => reject(err))
x.then(resolve, reject)
}else{
resolve(x)
}
} catch (error) {
reject(error)
}
// })
}
if(this.PromiseState === 'fulfilled'){
resolvePromise(onFulfilled)
}else if(this.PromiseState === 'rejected'){
resolvePromise(onRejected)
}else if(this.PromiseState === 'pending'){
this.onFulfilledCallbacks.push(resolvePromise.bind(this,onFulfilled))
this.onRejectedCallbacks.push(resolvePromise.bind(this,onRejected))
}
})
这样完整的代码就实现了:
class MyPromise {
constructor(executor){
this.initValue()
this.initBind()
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
initBind(){
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
}
initValue(){
this.PromiseState = 'pending'
this.PromiseResult = null
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
}
resolve(value){
if(this.PromiseState !== 'pending') return
this.PromiseState = "fulfilled"
this.PromiseResult = value
while(this.onFulfilledCallbacks.length){
this.onFulfilledCallbacks.shift()(this.PromiseResult)
}
}
reject(reason){
if(this.PromiseState !== 'pending') return
this.PromiseState = 'rejected'
this.PromiseResult = reason
while(this.onFulfilledCallbacks.length){
this.onRejectedCallbacks.shift()(this.PromiseResult)
}
}
then(onFulfilled,onRejected){
// 参数校验,确保一定是函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
const thenPromise = new MyPromise((resolve,reject) => {
const resolvePromise = (cb) => {
// setTimeout(() => {
try {
console.log(this)
let x = cb(this.PromiseResult)
if(x instanceof MyPromise){
// x.then(value => resolve(value),err => reject(err))
x.then(resolve, reject)
}else{
resolve(x)
}
} catch (error) {
reject(error)
}
// })
}
if(this.PromiseState === 'fulfilled'){
resolvePromise(onFulfilled)
}else if(this.PromiseState === 'rejected'){
resolvePromise(onRejected)
}else if(this.PromiseState === 'pending'){
this.onFulfilledCallbacks.push(resolvePromise.bind(this,onFulfilled))
this.onRejectedCallbacks.push(resolvePromise.bind(this,onRejected))
}
})
return thenPromise
}
}
const fn = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
},1000)
})
fn.then(res => {
return new MyPromise((resolve,reject) => {
resolve(res)
})
},err => {
console.log(err)
}).then(res1 => {
console.log(res1)
})