手写promise

promises

  • 首先,promise拥有三种状态,pending,fulfilled,rejected。
  • 分别为过渡态到成功态,过渡态到拒绝态,且不可逆。
  • promise拥有一个值保存数据,拥有一个状态决定功能,会有一个执行器函数。因此构造函数中拥有此三种变量或方法。
  • 执行器函数拥有两个函数分别为resolve,reject,分别保存成功的值和状态与失败的值和状态。
  • 此时我们需要解决的bug
    • resolve和reject只能调一次(加一个状态判断,捕获调用好多次的异常
  • then函数。then函数为resolve/reject执行之后的函数,因此需要添加一个状态。
  • 此时then需要捕获异常。
  • 此时我们需要解决的bug
    • promise异步执行,then会提前。(在构造函数中放一个数组,专门存放将要执行的函数,将值循环遍历出去
    • 捕获异常
    • 此时的promise执行顺序不对,原生promise中,当promise中的函数异步的时候,会先执行普通代码,异步代码放在下一步执行。(定时器异步操作
  • then的链式调用(返回一个promise
  • 此时then存在的问题
    • then的穿透,上方的判断如果函数为空,那么把空对象赋值给函数,此时把空对象改为静态数据
    • 返回值分为两类,一类是普通字符串,一类为promise对象,因此需要做一个判断
    • promise不可以在其中return自己(获取到promise自己,然后将自己与返回的数据做判断
  • promise的静态方法(promise对象可直接调用resolve/reject进行返回
  • promise的成员对象
    • promise.all(),将获取到的值放在数组中与promise的数量做一个判断
    • promise.race(),谁快用谁

用类的方法来写promise

声明HD.js

class HD{
//三种状态,pending->fulfilled,pending->rejected
//过度->成功,过渡->失败
  static PENDING='pending'
  static FULFILLED='fulfilled'
  static REJECTED='rejected'
  //构造函数,状态和传的值,以及改变状态的执行器
  constructor(executor){
    this.status=HD.PENDING
    this.value=null
    // 此bind()是在调用的时候改变this的指向到类,不然执行上下文调用的是window对象
    executor(this.resolve.bind(this),this.reject.bind(this))
  }
  // 修改成功时候的值和状态
  resolve(value){
    // console.log(this);
    this.status=HD.FULFILLED
    this.value=value
  }
  // 修改失败时候的值和状态
  reject(reason){
    // console.log(this);
    this.status=HD.REJECTED
    this.value=reason
  }
}

调用1.html

let p=new HD((resolve,reject)=>{
  // 如果在这里修改value的值与状态是不符合规范的,因为promise是不可逆的
  // resolve('解决')
  reject('拒绝')
})
console.log(p);

单向以及异常

使resolve与reject调用之后不可更改HD.js

resolve(value){
  // 只有在为pending的状态下才可以调用
  // 意思为只能调用一次
  if(this.status===HD.PENDING){
    this.status=HD.FULFILLED
    this.value=value
  }
}
reject(reason){
  // console.log(this);
  if(this.status===HD.PENDING){
    this.status=HD.REJECTED
    this.value=reason
  }
}

捕获异常HD.js

try {
  executor(this.resolve.bind(this),this.reject.bind(this))
} catch (error) {
  this.reject(error)
}

then

HD.js

then(onFulfilled,onRejected){
  // 获取reject状态改变之后的值
  // 成功才调
  if(this.status===HD.FULFILLED){
    onFulfilled(this.value)
  }
  if(this.status===HD.REJECTED){
    onRejected(this.value)
  }
}

拒绝的时候成功调用也不会报错

// 如果成功不为一个函数,那么定义成一个函数
if(typeof onFulfilled!=='function'){
  onFulfilled=()=>{}
}
// 如果失败不为一个函数,那么定义成一个函数
if(typeof onRejected!=='function'){
  onRejected=()=>{}
}

调用reject会使then成功的地方报错

then捕获异常

    if(this.status===HD.FULFILLED){
      try {
        // console.log('成功');
        onFulfilled(this.value)
      } catch (error) {
        // console.log('出错');
        onRejected(error)
      }
    }
    if(this.status===HD.REJECTED){
      try {
        // console.log('成功出错');
        onRejected(this.value)
      } catch (error) {
        // console.log('出错');
        onRejected(error)
      }
    }

promise异步那么.then就会提前执行

此时如果是promise异步,那么.then就会直接执行,.then中的内容就会获取不到异步中的状态

// 构造函数中定义一个数组,放将要执行的函数
this.callbacks=[];
// .then中,如果处于pending状态,那么不执行.then里边的函数,把函数压入callback数组中
if(this.status===HD.PENDING){
  this.callbacks.push({
    onFulfilled,
    onRejected
  })
}
// resolve()
// 如果执行过resolve,那么调用.then成功函数,把值传过去
this.callbacks.map(callback=>{
  callback.onFulfilled(value)
})
// ------------------------------------------------------------
// reject()
// 如果执行过reject,那么调用.then成功函数,把值传过去
this.callbacks.map(callback=>{
  callback.onRejected(reason)
})

准备状态异常错误捕获

// 如果处于pending状态,那么不执行.then里边的函数,把函数压入callback数组中
    if(this.status===HD.PENDING){
      this.callbacks.push({
        // 对象属性
        onFulfilled:value=>{
          // 执行的函数
          try {
            onFulfilled(value);
          } catch (error) {
            onRejected(error)
          }
        },
        onRejected:value=>{
          // 执行的函数
          try {
            onRejected(value);
          } catch (error) {
            onRejected(error)
          }
        },
      })
    }

更改调用promise执行逻辑顺序

当resolve中的函数异步的时候,调用方式是函数外部,异步中的函数,异步结果放在下一次的then中执行(先执行异步中的非resolve和reject),因此我们需要在调用resolve/reject的时候使用异步。

  resolve(value){
    // console.log(this);
    if(this.status===HD.PENDING){
      this.status=HD.FULFILLED
      this.value=value
      // 使用异步来改变逻辑顺序
      setTimeout(() => {
        // 如果执行过resolve,那么调用.then成功函数,把值传过去
        this.callbacks.map(callback=>{
          callback.onFulfilled(value)
        })
      });
    }
  }
  reject(reason){
    // console.log(this);
    if(this.status===HD.PENDING){
      this.status=HD.REJECTED
      this.value=reason
      setTimeout(() => {
        // 如果执行过reject,那么调用.then成功函数,把值传过去
        this.callbacks.map(callback=>{
          callback.onRejected(reason)
        }) 
      });
    }
  }

then链式调用接受前者参数

在这里插入图片描述
return promise
当前无法调用多次then,以及then的返回值

// then的最后
return new HD((resolve,reject)=>{
 // 其中包括then的所有操作
})
  then(onFulfilled,onRejected){
    // 如果成功不为一个函数,那么定义成一个函数
    // if(typeof onFulfilled!=='funciton'){
    //   onFulfilled=()=>{}
    // }
    // // 如果失败不为一个函数,那么定义成一个函数
    // if(typeof onRejected!=='funciton'){
    //   onRejected=()=>{}
    // }
    return new HD((resolve,reject)=>{
          // 如果处于pending状态,那么不执行.then里边的函数,把函数压入callback数组中
      if(this.status===HD.PENDING){
        this.callbacks.push({
          // 对象属性
          onFulfilled:value=>{
            // 执行的函数
            try {
              let result=onFulfilled(value)
              // 改变状态
              resolve(result)
              // onFulfilled(value);
            } catch (error) {
              onRejected(error)
            }
          },
          onRejected:value=>{
            // 执行的函数
            try {
              // onRejected(value);
              let result=onRejected(value)
              reject(result)
            } catch (error) {
              onRejected(error)
            }
          },
        })
      }
      // 获取reject状态改变之后的值
      // 成功才调
      if(this.status===HD.FULFILLED){
        setTimeout(() => {
          try {
            // console.log('成功');
            // 获取成功之后的返回值
            let result=onFulfilled(this.value)
            // 改变状态
            resolve(result)
          } catch (error) {
            // console.log('出错');
            onRejected('出错咯'+error)
          } 
        });
      }
      if(this.status===HD.REJECTED){
          setTimeout(() => {
            try {
            // console.log('成功出错');
            let result=onRejected(this.value)
            reject(result)
          } catch (error) {
            // console.log('出错');
            onRejected(error)
          }
        });
      }
    })
  }

新增链式promise异常处理

在上边的基础上直接调用reject而不是onRejected(error)

reject(error)

then的穿透

此时中间调用空的.then()就不会把值传递到下边的then

// 如果成功不为一个函数,那么定义成一个函数
if(typeof onFulfilled!=='function'){
  onFulfilled=()=>this.value
}
// 如果失败不为一个函数,那么定义成一个函数
if(typeof onRejected!=='function'){
  onRejected=()=>this.value
}

then return promise处理

当返回的值为promise对象时,进行判断

if(this.status===HD.FULFILLED){
  setTimeout(() => {
    try {
      // console.log('成功');
      // 获取成功之后的返回值
      let result=onFulfilled(this.value)
      // 改变状态
      // resolve(result)
      // 判断接受的是对象还是普通的字符串
      if(result instanceof HD){
        //如果是promise对象,那么再次调用then来返回得到的resolve的value
        result.then(resolve,reject)
        // 上述一行抵下面的所有
        // result.then(
        // value=>{
        //   resolve(value)
        // },
        // reason=>{
        //   reject(reason)
        // })
      }else{
        resolve(result)
      }
    } catch (error) {
      // console.log('出错');
      // onRejected('出错咯'+error)
      // 当发生异常时调用reject
      reject(error)
    } 
  });
}

代码冗余优化

优化前

class HD{
  static PENDING='pending'
  static FULFILLED='fulfilled'
  static REJECTED='rejected'
  constructor(executor){
    this.status=HD.PENDING
    this.value=null
    // 定义一个数组,放将要执行的函数
    this.callbacks=[];
    try {
      executor(this.resolve.bind(this),this.reject.bind(this))
    } catch (error) {
      this.reject(error)
    }
  }

  resolve(value){
    // console.log(this);
    if(this.status===HD.PENDING){
      this.status=HD.FULFILLED
      this.value=value
      // 使用异步来改变逻辑顺序
      setTimeout(() => {
        // 如果执行过resolve,那么调用.then成功函数,把值传过去
        this.callbacks.map(callback=>{
          callback.onFulfilled(value)
        })
      });
    }
  }

  reject(reason){
    // console.log(this);
    if(this.status===HD.PENDING){
      this.status=HD.REJECTED
      this.value=reason
      setTimeout(() => {
        // 如果执行过reject,那么调用.then成功函数,把值传过去
        this.callbacks.map(callback=>{
          callback.onRejected(reason)
        }) 
      });
    }
  }

  then(onFulfilled,onRejected){
    // 如果成功不为一个函数,那么定义成一个函数
    if(typeof onFulfilled!=='function'){
      onFulfilled=()=>this.value
    }
    // 如果失败不为一个函数,那么定义成一个函数
    if(typeof onRejected!=='function'){
      onRejected=()=>this.value
    }
    return new HD((resolve,reject)=>{
          // 如果处于pending状态,那么不执行.then里边的函数,把函数压入callback数组中
      if(this.status===HD.PENDING){
        this.callbacks.push({
          // 对象属性
          onFulfilled:value=>{
            // 执行的函数
            try {
              let result=onFulfilled(value)
              // 改变状态
              // resolve(result)
              if(result instanceof HD){
                result.then(resolve,reject)
              }else{
                resolve(result)
              }
              // onFulfilled(value);
            } catch (error) {
              // onRejected(error)
              reject(error)
            }
          },
          onRejected:value=>{
            // 执行的函数
            try {
              // onRejected(value);
              let result=onRejected(value)
              // reject(result)
              if(result instanceof HD){
                result.then(resolve,reject)
              }else{
                resolve(result)
              }
            } catch (error) {
              // onRejected(error)
              reject(error)
            }
          },
        })
      }
      // 获取reject状态改变之后的值
      // 成功才调
      if(this.status===HD.FULFILLED){
        setTimeout(() => {
          try {
            // console.log('成功');
            // 获取成功之后的返回值
            let result=onFulfilled(this.value)
            // 改变状态
            // resolve(result)
            // 判断接受的是对象还是普通的字符串
            if(result instanceof HD){
              //如果是promise对象,那么再次调用then来返回得到的resolve的value
              result.then(resolve,reject)
              // 上述一行抵下面的所有
              // result.then(
              // value=>{
              //   resolve(value)
              // },
              // reason=>{
              //   reject(reason)
              // })
            }else{
              resolve(result)
            }
          } catch (error) {
            // console.log('出错');
            // onRejected('出错咯'+error)
            // 当发生异常时调用reject
            reject(error)
          } 
        });
      }
      if(this.status===HD.REJECTED){
          setTimeout(() => {
            try {
            // console.log('成功出错');
            let result=onRejected(this.value)
            // reject(result)
            if(result instanceof HD){
              result.then(resolve,reject)
            }else{
              resolve(result)
            }
          } catch (error) {
            // console.log('出错');
            // onRejected(error)
            reject(error)
          }
        });
      }
    })
  }
}


优化后

// 优化代码
parse(result,resolve,reject){
  try {
    if(result instanceof HD){
      result.then(resolve,reject)
    }else{
      resolve(result)
    }
  } catch (error) {
    reject(error)
  } 
}

// 调用函数举例
if(this.status===HD.FULFILLED){
  setTimeout(() => {
    this.parse(onFulfilled(this.value),resolve,reject)
  });
}
if(this.status===HD.REJECTED){
  setTimeout(() => {
    this.parse(onRejected(this.value),resolve,reject)
  });
}

promise不允许return自己

虽然是异步,但是不允许返回自己

//加上promise来与result做一次比较
parse(promise,result,resolve,reject){
   if(promise===result){
     throw new TypeError('Chaining cycle detected')
   }
   try {
     if(result instanceof HD){
       result.then(resolve,reject)
     }else{
       resolve(result)
     }
   } catch (error) {
     reject(error)
   } 
 }
// 得到promise
let promise= new HD((resolve,reject)=>{}
return promise;

reject与resolve的静态方法

直接调用

// 测试
let promise=new HD((resolve,reject)=>{
  resolve('解决')
})
HD.resolve(promise).then(value=>{
  console.log(value);
})
  static resolve(value){
    return new HD((resolve,reject)=>{
      if(value instanceof HD){
        value.then(resolve,reject)
      }else{
        resolve(value)
      }
    })
  }

  static reject(value){
    return new HD((resolve,reject)=>{
      reject(value)
    })
  }

promise.all()

获取全部的promise,而且全部判断是否成功

static all(promises){
  const values=[]
  return new HD((resolve,reject)=>{
    promises.forEach((promise=>{
      promise.then(
        value=>{
          values.push(value)
          if(values.length==promises.length){
            resolve(values)
          }
      },reason=>{
          reject(reason)
      })
    }))
  })
}

promise.race()

谁快用谁

static race(promises){
  return new HD((resolve,reject)=>{
    promises.map(promise=>{
      promise.then(value=>{
        resolve(value)
      },reason=>{
        reject(reason)
      })
    })
  })
}

完整代码

class HD{
  static PENDING='pending'
  static FULFILLED='fulfilled'
  static REJECTED='rejected'
  constructor(executor){
    this.status=HD.PENDING
    this.value=null
    // 定义一个数组,放将要执行的函数
    this.callbacks=[];
    try {
      executor(this.resolve.bind(this),this.reject.bind(this))
    } catch (error) {
      this.reject(error)
    }
  }

  resolve(value){
    // console.log(this);
    if(this.status===HD.PENDING){
      this.status=HD.FULFILLED
      this.value=value
      // 使用异步来改变逻辑顺序
      setTimeout(() => {
        // 如果执行过resolve,那么调用.then成功函数,把值传过去
        this.callbacks.map(callback=>{
          callback.onFulfilled(value)
        })
      });
    }
  }

  reject(reason){
    // console.log(this);
    if(this.status===HD.PENDING){
      this.status=HD.REJECTED
      this.value=reason
      setTimeout(() => {
        // 如果执行过reject,那么调用.then成功函数,把值传过去
        this.callbacks.map(callback=>{
          callback.onRejected(reason)
        }) 
      });
    }
  }

  then(onFulfilled,onRejected){
    // 如果成功不为一个函数,那么定义成一个函数
    if(typeof onFulfilled!=='function'){
      onFulfilled=()=>this.value
    }
    // 如果失败不为一个函数,那么定义成一个函数
    if(typeof onRejected!=='function'){
      onRejected=()=>this.value
    }
    let promise= new HD((resolve,reject)=>{
      // 如果处于pending状态,那么不执行.then里边的函数,把函数压入callback数组中
      if(this.status===HD.PENDING){
        this.callbacks.push({
          // 对象属性
          onFulfilled:value=>{
            this.parse(promise,onFulfilled(value),resolve,reject)
          },
          onRejected:value=>{
            this.parse(promise,onRejected(value),resolve,reject)
          },
        })
      }
      // 获取reject状态改变之后的值
      // 成功才调
      if(this.status===HD.FULFILLED){
        setTimeout(() => {
          this.parse(promise,onFulfilled(this.value),resolve,reject)
        });
      }
      if(this.status===HD.REJECTED){
        setTimeout(() => {
          this.parse(promise,onRejected(this.value),resolve,reject)
        });
      }
    })
    return promise;
  }

  // 优化代码
  parse(promise,result,resolve,reject){
    if(promise===result){
      throw new TypeError('Chaining cycle detected')
    }
    try {
      if(result instanceof HD){
        result.then(resolve,reject)
      }else{
        resolve(result)
      }
    } catch (error) {
      reject(error)
    } 
  }

  static resolve(value){
    return new HD((resolve,reject)=>{
      if(value instanceof HD){
        value.then(resolve,reject)
      }else{
        resolve(value)
      }
    })
  }

  static reject(value){
    return new HD((resolve,reject)=>{
      reject(value)
    })
  }

  static all(promises){
    const values=[]
    return new HD((resolve,reject)=>{
      promises.forEach((promise=>{
        promise.then(
          value=>{
            values.push(value)
            if(values.length==promises.length){
              resolve(values)
            }
        },reason=>{
            reject(reason)
        })
      }))
    })
  }

  static race(promises){
    return new HD((resolve,reject)=>{
      promises.map(promise=>{
        promise.then(value=>{
          resolve(value)
        },reason=>{
          reject(reason)
        })
      })
    })
  }
}

参考视频教程:手写PROMISE核心

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!以下是一个简单的手写Promise的示例: ```javascript class Promise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolveCallbacks = []; this.onRejectCallbacks = []; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onResolveCallbacks.forEach(callback => callback()); } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectCallbacks.forEach(callback => callback()); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { const fulfilledHandler = typeof onFulfilled === 'function' ? onFulfilled : value => value; const rejectedHandler = typeof onRejected === 'function' ? onRejected : reason => { throw reason; }; const promise2 = new Promise((resolve, reject) => { const fulfillHandlerWrapper = () => { setTimeout(() => { try { const result = fulfilledHandler(this.value); resolvePromise(promise2, result, resolve, reject); } catch (error) { reject(error); } }, 0); }; const rejectHandlerWrapper = () => { setTimeout(() => { try { const result = rejectedHandler(this.reason); resolvePromise(promise2, result, resolve, reject); } catch (error) { reject(error); } }, 0); }; if (this.state === 'fulfilled') { fulfillHandlerWrapper(); } else if (this.state === 'rejected') { rejectHandlerWrapper(); } else { this.onResolveCallbacks.push(fulfillHandlerWrapper); this.onRejectCallbacks.push(rejectHandlerWrapper); } }); return promise2; } catch(onRejected) { return this.then(null, onRejected); } } function resolvePromise(promise, result, resolve, reject) { if (promise === result) { return reject(new TypeError('Chaining cycle detected for promise')); } let thenCalledOrThrow = false; if (result instanceof Promise) { result.then( value => resolvePromise(promise, value, resolve, reject), reason => reject(reason) ); } else if (result !== null && (typeof result === 'object' || typeof result === 'function')) { try { const then = result.then; if (typeof then === 'function') { then.call( result, value => { if (thenCalledOrThrow) return; thenCalledOrThrow = true; resolvePromise(promise, value, resolve, reject); }, reason => { if (thenCalledOrThrow) return; thenCalledOrThrow = true; reject(reason); } ); } else { resolve(result); } } catch (error) { if (thenCalledOrThrow) return; thenCalledOrThrow = true; reject(error); } } else { resolve(result); } } ``` 这只是一个基本的实现,还有很多细节和功能可以改进。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值