分析Promise的基本使用
- Promise就是一个类
class MyPromise {}
- 执行这个类的时候,需要传递一个执行器(回调函数),执行器会立即执行
class MyPromise{
constructor(executor){
executor()
}
}
- 执行器有两个参数,resolve和reject 为两个函数
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
resolve = () =>{
}
reject = () =>{
}
}
- Promise有三种状态(status)分别为: 成功(fulfilled) 失败(rejected) 等待(pending)。
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING
resolve = () =>{
}
reject = () =>{
}
}
5.resolve :把Promise 状态改为 fulfilled ;reject把Promise 状态改为rejected
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING
resolve = () =>{
this.status = FULFILLED
}
reject = () =>{
this.status = REJECTED
}
}
- 一旦状态确定就不可更改 比如 pending --> fulfilled ;pending --> rejected
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING
resolve = () =>{
if(this.status !== PENDING) return
this.status = FULFILLED
}
reject = () =>{
if(this.status !== PENDING) return
this.status = REJECTED
}
}
- resolve 参数为成功后的数据;reject 参数为失败之后的原因
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING
data = undefined
reason = undefined
resolve = data =>{
if(this.status !== PENDING) return
this.status = FULFILLED
this.data = data
}
reject = reason =>{
if(this.status !== PENDING) return
this.status = REJECTED
this. reason = reason
}
}
- then 方法被定义在原型对象中,then方法内部做的事情就是判断状态,如果成功,调用成功的回调,参数为成功的数据,如果失败,调用失败的回调,参数为失败的原因
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING
data = undefined
reason = undefined
resolve = data =>{
if(this.status !== PENDING) return
this.status = FULFILLED
this.data = data
}
reject = reason =>{
if(this.status !== PENDING) return
this.status = REJECTED
this. reason = reason
}
then(successCallback,failCallback){
if(this.status === FULFILLED){
successCallback(this.data)
} else if (this.status === REJECTED){
failCallback(this.reason)
}
}
}
8.执行器中有异步操作时,then不会立即得到成功还是失败的状态,因此需要把成功后的回调和失败后的回调存储起来,等待异步操作完成后再执行对应的回调
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING
data = undefined
reason = undefined
successCallback = undefined
failCallback = undefined
resolve = data =>{
if(this.status !== PENDING) return
this.status = FULFILLED
this.data = data
this.successCallback && this.successCallback(this.data)
}
reject = reason =>{
if(this.status !== PENDING) return
this.status = REJECTED
this. reason = reason
this.failCallback && this.failCallback(this.reason)
}
then(successCallback,failCallback){
if(this.status === FULFILLED){
successCallback(this.data)
} else if (this.status === REJECTED){
failCallback(this.reason)
} else {
this.successCallback = successCallback
this.failCallback = failCallback
}
}
}
9.同一个Promise对象,多次调用then方法时,异步情况需要添加多个回调函数依次执行,做以下修改
修改成功回调和失败回调的数据类型为数组
then方法中Promise为等待的状态时,push成功回调和失败回调到数组
异步操作完成后,按顺序执行成功或失败的回调函数
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING
data = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = data =>{
if(this.status !== PENDING) return
this.status = FULFILLED
this.data = data
//this.successCallback && this.successCallback(this.data)
while(this.successCallback.length) this.successCallback.shift()(this.data)
}
reject = reason =>{
if(this.status !== PENDING) return
this.status = REJECTED
this. reason = reason
//this.failCallback && this.failCallback(this.reason)
while(this.failCallback.length) this.failCallback.shift()(this.reason)
}
then(successCallback,failCallback){
if(this.status === FULFILLED){
successCallback(this.data)
} else if (this.status === REJECTED){
failCallback(this.reason)
} else {
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
}
}
10.实现then方法的链式调用,做以下修改
then方法每次要返回一个新的Promise对象
处理then方法的返回值(非Promise类型)到新的Promise对象执行器的reslove方法中,以实现链式调用时返回值的传递
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING
data = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = data =>{
if(this.status !== PENDING) return
this.status = FULFILLED
this.data = data
//this.successCallback && this.successCallback(this.data)
while(this.successCallback.length) this.successCallback.shift()(this.data)
}
reject = reason =>{
if(this.status !== PENDING) return
this.status = REJECTED
this. reason = reason
//this.failCallback && this.failCallback(this.reason)
while(this.failCallback.length) this.failCallback.shift()(this.reason)
}
then(successCallback,failCallback){
return new MyPromise((resolve,reject) => {
if(this.status === FULFILLED){
let returnValue = successCallback(this.data)
resolve(returnValue)
} else if (this.status === REJECTED){
failCallback(this.reason)
} else {
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
})
}
}
10.1 当then 方法成功的回调函数中,返回的是一个Promise对象时,做以下修改
判断returnValue的类型
如果是Promise创建的实例,则需要把成功还是失败的回调传递到新的Promise对象中以实现链式调用
如果是非Promise创建的实例,则需要把返回值(returnValue)传递到reslove中
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING
data = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = data =>{
if(this.status !== PENDING) return
this.status = FULFILLED
this.data = data
//this.successCallback && this.successCallback(this.data)
while(this.successCallback.length) this.successCallback.shift()(this.data)
}
reject = reason =>{
if(this.status !== PENDING) return
this.status = REJECTED
this. reason = reason
//this.failCallback && this.failCallback(this.reason)
while(this.failCallback.length) this.failCallback.shift()(this.reason)
}
then(successCallback,failCallback){
return new MyPromise((resolve,reject) => {
if(this.status === FULFILLED){
let returnValue = successCallback(this.data)
if(returnValue instanceof MyPromise){
returnValue.then(resolve,reject)
} else {
resolve(returnValue)
}
} else if (this.status === REJECTED){
failCallback(this.reason)
} else {
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
})
}
}
11.异常处理,当then方法的成功回调函数中,返回then方法返回的Promise对象时,也就是自己调用自己的情况,系统中的Promise对象会抛出TypeError的异常。对我们的MyPromise做以下修改以捕获类似异常
在then方法中做判断,返回新的Promise对象与成功回调返回的值(returnValue)相等的时候,调用新的Promise的rejece方法并传入类型异常
把判断的代码做成异步代码,不然无法拿到新的Promise对象 (setTimeout 0)
添加新方法 resolvePromise 用来判断then方法成功回调的返回值
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING
data = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = data =>{
if(this.status !== PENDING) return
this.status = FULFILLED
this.data = data
//this.successCallback && this.successCallback(this.data)
while(this.successCallback.length) this.successCallback.shift()(this.data)
}
reject = reason =>{
if(this.status !== PENDING) return
this.status = REJECTED
this. reason = reason
//this.failCallback && this.failCallback(this.reason)
while(this.failCallback.length) this.failCallback.shift()(this.reason)
}
then(successCallback,failCallback){
let newMyPromise = new MyPromise((resolve,reject) => {
if(this.status === FULFILLED){
setTimeout(() => {
let returnValue = successCallback(this.data)
resolvePromise(newMyPromise,returnValue,resolve,reject)
}, 0);
} else if (this.status === REJECTED){
failCallback(this.reason)
} else {
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
})
return newMyPromise
}
}
function resolvePromise (newMyPromise,returnValue,resolve,reject){
if(newMyPromise === returnValue){
reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}else{
if(returnValue instanceof MyPromise){
returnValue.then(resolve,reject)
} else {
resolve(returnValue)
}
}
}
12 捕获及处理执行器和then方法的成功回调函数的异常以及then方法中失败和等待时链式调用的实现
给执行器和then方法的回调函数加上异常处理
把then方法失败和等待状态的链式调用实现成之前成功状态的代码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
try{
executor(this.resolve,this.reject)
}catch(error){
this.reject(error)
}
}
status = PENDING
data = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = data =>{
if(this.status !== PENDING) return
this.status = FULFILLED
this.data = data
while(this.successCallback.length) this.successCallback.shift()()
}
reject = reason =>{
if(this.status !== PENDING) return
this.status = REJECTED
this. reason = reason
while(this.failCallback.length) this.failCallback.shift()()
}
then(successCallback,failCallback){
let newMyPromise = new MyPromise((resolve,reject) => {
if(this.status === FULFILLED){
setTimeout(() => {
try{
let returnValue = successCallback(this.data)
resolvePromise(newMyPromise,returnValue,resolve,reject)
}catch(error){
reject(error)
}
}, 0);
} else if (this.status === REJECTED){
setTimeout(() => {
try{
let returnValue = failCallback(this.reason)
resolvePromise(newMyPromise,returnValue,resolve,reject)
}catch(error){
reject(error)
}
}, 0);
} else {
this.successCallback.push(()=>{
setTimeout(() => {
try{
let returnValue = successCallback(this.data)
resolvePromise(newMyPromise,returnValue,resolve,reject)
}catch(error){
reject(error)
}
}, 0);
})
this.failCallback.push(() =>{
setTimeout(() => {
try{
let returnValue = failCallback(this.reason)
resolvePromise(newMyPromise,returnValue,resolve,reject)
}catch(error){
reject(error)
}
}, 0);
})
}
})
return newMyPromise
}
}
function resolvePromise (newMyPromise,returnValue,resolve,reject){
if(newMyPromise === returnValue){
reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}else{
if(returnValue instanceof MyPromise){
returnValue.then(resolve,reject)
} else {
resolve(returnValue)
}
}
}
13.将then 方法的参数变成可选参数,也就是说 当then方法链式调用的时候 先不传参数 后面的then再穿参数,也可以调用then的回调函数
做法就是判断then的参数如果为空,补上成功或失败的回调函数
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
constructor(executor){
try{
executor(this.resolve,this.reject)
}catch(error){
this.reject(error)
}
}
status = PENDING
data = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = data =>{
if(this.status !== PENDING) return
this.status = FULFILLED
this.data = data
while(this.successCallback.length) this.successCallback.shift()()
}
reject = reason =>{
if(this.status !== PENDING) return
this.status = REJECTED
this. reason = reason
while(this.failCallback.length) this.failCallback.shift()()
}
then(successCallback,failCallback){
let newMyPromise = new MyPromise((resolve,reject) => {
if(this.status === FULFILLED){
setTimeout(() => {
try{
if(!successCallback) successCallback = value => value
let returnValue = successCallback(this.data)
resolvePromise(newMyPromise,returnValue,resolve,reject)
}catch(error){
reject(error)
}
}, 0);
} else if (this.status === REJECTED){
setTimeout(() => {
try{
if(!failCallback) failCallback = reason => { throw reason }
let returnValue = failCallback(this.reason)
resolvePromise(newMyPromise,returnValue,resolve,reject)
}catch(error){
reject(error)
}
}, 0);
} else {
this.successCallback.push(()=>{
setTimeout(() => {
try{
if(!successCallback) successCallback = value => value
let returnValue = successCallback(this.data)
resolvePromise(newMyPromise,returnValue,resolve,reject)
}catch(error){
reject(error)
}
}, 0);
})
this.failCallback.push(() =>{
setTimeout(() => {
try{
if(!failCallback) failCallback = reason => { throw reason }
let returnValue = failCallback(this.reason)
resolvePromise(newMyPromise,returnValue,resolve,reject)
}catch(error){
reject(error)
}
}, 0);
})
}
})
return newMyPromise
}
}
function resolvePromise (newMyPromise,returnValue,resolve,reject){
if(newMyPromise === returnValue){
reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}else{
if(returnValue instanceof MyPromise){
returnValue.then(resolve,reject)
} else {
resolve(returnValue)
}
}
}
14.Promise.all 方法的实现
static all (array){
let result = []
return new MyPromise(async (resolve,reject) =>{
for(let item of array){
if(item instanceof MyPromise){
try{
result.push(await item)
}catch(error){
reject(error)
}
}else{
result.push(item)
}
}
resolve(result)
})
}
上面是直接拍扁异步操作或者等待异步操作完成以后,再去resolve,两个方式都可以实现all方法
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){
resolve(result)
}
}
for(let i = 0; i < array.length; i++){
if(array[i] instanceof MyPromise){
array[i].then(value => addData(i,value), error => reject(error))
}else{
addData(i,array[i])
}
}
})
}
15.Promise.resolve方法的实现
static resolve(value){
if(value instanceof MyPromise){
return value
}else{
return new MyPromise(resolve =>resolve(value))
}
}
16.finally 方法的实现
finally(Callback){
return this.then(value =>{
return MyPromise.resolve(Callback()).then(() => value)
},error =>{
return MyPromise.resolve(Callback()).then(() => { throw error })
})
}
17.catch 方法的实现
catch(failCallback){
return this.then(undefined,failCallback)
}