手写promise笔记

promiss

基础版

**promise解决的问题 **

  1. 等待多个异步请求结束 promise.all

  2. 链式调用,上一个请求结果是下一个请求的参数等,解决回调地狱 promise.then

    _ 缺陷: 还是基于回调的,只是写法更优雅

promise 的特点

  1. promise 是个类
  2. promise有三个状态, resolve(成功) reject(失败) pendding(等待)
  3. promise 默认执行器立即执行
  4. 用户可以自己决定成功还是失败的状态
  5. promise都有then方法,默认有两个参数,成功的回调,可以拿到成功态的参数;失败的回调,可以拿到失败态的参数
  6. 如果执行函数时发生了异常,就走到了失败态
  7. 一旦成功态了就不能再失败了,失败态也不能再转到成功; 状态不可逆转
// 简单版promise
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
const PENDDING = 'PENDDING'
class Promise1 {
  constructor(executor) {
    this.value = undefined
    this.reason = undefined
    this.state = PENDDING
    let resolve = (data) => {
      if (this.state === PENDDING) {
        console.log()
        this.state = RESOLVED
        this.value = data
      }
    }
    let reject = (data) => {
      if (this.state === PENDDING) {
        this.state = REJECTED
        this.reason = data
      }
    }
    try {
      // throw new Error("抛出错误");
      executor(resolve, reject)

    } catch (err) {
      reject(err)
    }

  }
  then(onFulfilled, onRejected) {
    if (this.state === RESOLVED) {
      onFulfilled(this.value)
    }
    if (this.state === REJECTED) {
      onRejected(this.reason)
    }
  }
}

let p = new Promise1((resolve, reject) => {
  console.log('立即执行')
  resolve('成功')
  // reject('失败啦')
})
p.then((res) => { console.log('成功', res) }, (err) => { console.log('失败' + err) })
异步 调用

上面简版promise

待解决问题有1️⃣ promise 调用then时,如果异步,resolve或者reject没有完成, pedding状态,不能拿到执行后的额结果

解决方法:用发布订阅模式, then的成功回调和失败回调都存起来, 等异步结束,pengdding状态改变,再依次执行

const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
const PENDDING = 'PENDDING'
class Promise1 {
  constructor(executor) {
    this.value = undefined
    this.reason = undefined
    this.state = PENDDING
   // ----------   新增代码
    this.onResolvedCallbacks = []
    this.onRejectedCallbacks = []
    //-------
    let resolve = (data) => {
      if (this.state === PENDDING) {
        console.log()
        this.state = RESOLVED
        this.value = data
          // -------- 发布事件
        this.onResolvedCallbacks.forEach(i => i())
          // --------
      }
    }
    let reject = (data) => {
      if (this.state === PENDDING) {
        this.state = REJECTED
        this.reason = data
          // ----- 发布事件
        this.onRejectedCallbacks.forEach(i => i())
          // -----
      }
    }
    try {
      // throw new Error("loopTerminates");
      executor(resolve, reject)

    } catch (err) {
      reject(err)
    }

  }
  then(onFulfilled, onRejected) {
    if (this.state === RESOLVED) {
      onFulfilled(this.value)
    }
    if (this.state === REJECTED) {
      onRejected(this.reason)
    }
      // -------------- 异步,状态为pendding,先订阅事件
    if (this.state === PENDDING) {
      this.onResolvedCallbacks.push(() => {
        onFulfilled(this.value)
      })
      this.onRejectedCallbacks.push(() => {
        onRejected(this.reason)
      })
    }
      // ---------------
  }
}

let p = new Promise1((resolve, reject) => {
  console.log('立即执行')
  setTimeout(() => {
    resolve('成功')
  }, 200);

  // reject('失败啦')
})
p.then((res) => { console.log('成功', res) }, (err) => { console.log('失败' + err) })
p.then((res) => { console.log('成功2', res) }, (err) => { console.log('失败2' + err) })

then特性

promise then 特性

  1. promise 失败和成功的返回值可以传递到下一个then里面

  2. 如果返回值是普通值, 传递到下一个then的成功回调里.

    如果抛出错误,传递到失败回调里;

    如果返回值是promise,则根据promise的结果,resolve就传递到成功回调,reject就传递到失败回调里

  3. 错误处理,如果最近的then里面没有错误处理,会向下找错误回调,处理错误

  4. promise.then返回一个新的promise 而不是this(因为promise状态不可逆,不会成功转失败等)

const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
const PENDDING = 'PENDDING'
// -------根绝返回值x确定如果处理promise结果
function resolvePromise(promise2, x, resolve, reject) {

  if (promise2 === x) { // 自己调自己,报类型错误
    throw new Error('TypeError')
  }
  let called; // unfined 用于处理别人得posmise可能出现先成功又失败等情况;
  if ((typeof x === 'object' && x != null) || typeof x === 'function') {
    try {
      // x 是对象或者函数,有可能是promise
      let then = x.then
      if (typeof then === 'function') {
        // 假定是promise
        then.call(x, y => {

          if (called) return
          called = true // 成功,失败,异常,只能调用一次,promise状态不能更改
          // 成功回调
          resolvePromise(promise2, y, resolve, reject) // 递归解析,如果resolve返回一个promise

        }, e => {
          if (called) return
          called = true
          // 失败回调
          reject(e)
        })
      } else { // 普通对象,刚好有then方法

        resolve(x)
      }
    } catch (e) {
      if (called) return
      called = true
      reject(e)
    }

  } else { // x 是普通值
    resolve(x)
  }
}
// --------方法结束
class Promise1 {
  constructor(executor) {
    this.value = undefined
    this.reason = undefined
    this.state = PENDDING
    this.onResolvedCallbacks = []
    this.onRejectedCallbacks = []
    let resolve = (data) => {
      if (this.state === PENDDING) {
        console.log()
        this.state = RESOLVED
        this.value = data
        this.onResolvedCallbacks.forEach(i => i())
      }
    }
    let reject = (data) => {
      if (this.state === PENDDING) {
        this.state = REJECTED
        this.reason = data
        this.onRejectedCallbacks.forEach(i => i())
      }
    }
    try {
      // throw new Error("loopTerminates");
      executor(resolve, reject)

    } catch (err) {
      reject(err)
    }

  }
  then(onFulfilled, onRejected) {
      // 返回的promise2 
    let promise2 = new Promise1((resolve, reject) => {
      if (this.state === RESOLVED) {
        setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
          // 1,x是普通值,还是promise? 2,怎么处理x  
          try {
            let x = onFulfilled(this.value)
            // 处理x和promise返回值
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }

        }, 0)
      }
      if (this.state === REJECTED) {
        setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
          // 1,x是普通值,还是promise? 2,怎么处理x  
          try {
            let x = onRejected(this.reason)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }

        }, 0)

      }
      if (this.state === PENDDING) {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
            // 1,x是普通值,还是promise? 2,怎么处理x         
            try {
              let x = onFulfilled(this.value)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
            // 1,x是普通值,还是promise? 2,怎么处理x         
            try {
              let x = onRejected(this.reason)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
      }
    })

    return promise2

  }
}

let p1 = new Promise1((resolve, reject) => {
  throw new Error('抛出错误信息');
  resolve('111')
})
let p2 = p1.then((data) => {
  return new Promise1((resolve, reject) => {
    setTimeout(() => {
      resolve(new Promise1((resolve, reject) => {
        resolve('20000')
      }))
    }, 500)

  })
}, e => {
  console.log('===', e)
})
// reject('失败啦')

p2.then((res) => { console.log('成功', res) }, (err) => { console.log('失败' + err) })
最终版
  • 添加then穿透,; resolve,reject传参不是function时,自动补全函数,参数下传
  • promises-aplus-tests promise规则校验
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
const PENDDING = 'PENDDING'
function resolvePromise(promise2, x, resolve, reject) {

  if (promise2 === x) { // 自己调自己,报类型错误
    return reject(new TypeError('TypeError'))
  }
  let called; // unfined 用于处理别人得posmise可能出现先成功又失败等情况;
  if ((typeof x === 'object' && x != null) || typeof x === 'function') {
    try {
      // x 是对象或者函数,有可能是promise
      let then = x.then
      if (typeof then === 'function') {
        // 假定是promise
        then.call(x, y => {

          if (called) return
          called = true // 成功,失败,异常,只能调用一次,promise状态不能更改
          // 成功回调
          resolvePromise(promise2, y, resolve, reject) // 递归解析,如果resolve返回一个promise

        }, e => {
          if (called) return
          called = true
          // 失败回调
          reject(e)
        })
      } else { // 普通对象,刚好有then方法

        resolve(x)
      }
    } catch (e) {
      if (called) return
      called = true
      reject(e)
    }

  } else { // x 是普通值
    resolve(x)
  }

}
class Promise1 {
  constructor(executor) {
    this.value = undefined
    this.reason = undefined
    this.state = PENDDING
    this.onResolvedCallbacks = []
    this.onRejectedCallbacks = []
    let resolve = (data) => {
      if (this.state === PENDDING) {
        console.log()
        this.state = RESOLVED
        this.value = data
        this.onResolvedCallbacks.forEach(i => i())
      }
    }
    let reject = (data) => {
      if (this.state === PENDDING) {
        this.state = REJECTED
        this.reason = data
        this.onRejectedCallbacks.forEach(i => i())
      }
    }
    try {
      // throw new Error("loopTerminates");
      executor(resolve, reject)

    } catch (err) {
      reject(err)
    }

  }
  then(onFulfilled, onRejected) {
    // onFulfilled, onRejected 可选参数,如果没有值,默认透传
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
    let promise2 = new Promise1((resolve, reject) => {
      if (this.state === RESOLVED) {
        setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
          // 1,x是普通值,还是promise? 2,怎么处理x  
          try {
            let x = onFulfilled(this.value)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }

        }, 0)
      }
      if (this.state === REJECTED) {
        setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
          // 1,x是普通值,还是promise? 2,怎么处理x  
          try {
            let x = onRejected(this.reason)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }

        }, 0)

      }
      if (this.state === PENDDING) {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
            // 1,x是普通值,还是promise? 2,怎么处理x         
            try {
              let x = onFulfilled(this.value)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => { // 异步,才能在下面resolvePromise中拿到promise2的值
            // 1,x是普通值,还是promise? 2,怎么处理x         
            try {
              let x = onRejected(this.reason)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
      }
    })

    return promise2

  }
}

// let p1 = new Promise1((resolve, reject) => {
// reject('222')
// throw new Error('抛出错误信息');
// resolve('111')
// })
// let p2 = p1.then((data) => {
//   return new Promise1((resolve, reject) => {
//     setTimeout(() => {
//       resolve(new Promise1((resolve, reject) => {
//         resolve('20000')
//       }))
//     }, 500)

//   })
// }, e => {
//   console.log('===', e)
// })
// reject('失败啦')

// p1.then().then().then((res) => { console.log('成功', res) }, (err) => { console.log('失败' + err) })

// 用 promises-aplus-tests 进行测试
Promise1.defer = Promise1.deferred = function () {
  let dfd = {};
  dfd.promise = new Promise1((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
}
module.exports = Promise1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值