彻底掌握Promise-原生Promise的实现(一) Promise 的简易版本

32 篇文章 2 订阅
8 篇文章 0 订阅

Promise简介

        在ES6(ES2015)正式发布中,Promise 被列为正式规范,作为ES6中最重要的特性之一。

        Promise 的出现主要是为了解决回调地狱问题,通过调用 .then 方法逐层去向下调用

    1.            

Promise 对象有以下两个特点:

1、对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:

  • pending: 初始状态,不是成功或失败状态。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。

2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。

Promise的用法

  Promise 的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。其实这里用 “成功” 和 “失败” 来描述并不准确,按照标准来讲,resolve 是将 Promise 的状态置为 fullfiled,reject 是将 Promise 的状态置为 rejected 。

let promi = new Promise((resolve, reject) => {
    resolve('new promise111111')
    // reject('error')
})
/*
  在promise中我们可以手动去调用resolve, reject去执行成功/失败的状态
  !!!!!!promise中的状态由pedding变更为其他状态后就不可再次更改了

*/

promi.then(res => {
// 这里拿到的就是resolve中传入的参数
    console.log(res);
}, reason => {
// 这里拿到的就是reject中传入的参数
    console.log(reason);
})

实现一个原生简易版本的 Promise

    我们可以根据 Promise 的使用方式来逆解析它内部的处理逻辑

  1. 它接收一个匿名函数来作为参数
  2. 使用 resolve 方法返回成功状态
  3. 使用 reject 方法返回失败状态
  4. 调用 then 方法去处理成功/失败的状态

具体实现

  1. 通过 class 关键字创建一个类出来
  2. 在类中使用 constructor 方法接收外部传入过来的匿名函数
  3. promise 的状态一经变更就不在更改
  4. 执行这个匿名函数, 并传入 resolve, reject 方法
  5. then 方法的处理
  6. 处理异步情况

基本实现

// 保存Promise的三个状态, 以便后续调用
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class iPromise {

  constructor(callback) {
    // 接收执行外部传入的匿名函数
    callback(this.resolve, this.reject)
  }

  value = null // --> 成功的值
  status = PENDING // --> promise声明时默认为pending(执行中)的状态
  reason = null // --> 失败的原因

  resolve = (value) => {
    // 判断当前promise的状态是否已经变更过, 如果变更过就不做任何操作
    if (this.status !== PENDING) {
        return
    }
    // 变更promise的状态, 并获取promise的成功参数保存到promise内, 在成功的回调中暴露出去
    this.status = FULFILLED
    this.value = value
  }

  reject = (reason) => {
    // 判断当前promise的状态是否已经变更过, 如果变更过就不做任何操作
    if (this.status !== PENDING) {
        return
    }
    // 变更promise的状态, 并获取promise的失败参数, 在失败的回调中暴露出去
    this.status = REJECTED
    this.reason = reason
  }
  then(successCallback, errorCallback) {
    if (this.status == FULFILLED) {
      successCallback(this.value)
    } else if (this.status == REJECTED) {
      errorCallback(this.reason)
    }
  }
}

写到这一步这样可以基本实现简易版本 Promise 第一步了

let promise = new iPromise((resolve, reject) => {
        resolve('new promise')
      // reject('reaspn')
    })

    promise.then(res => {
      console.log(res);// new Promises
    }, reason => {
      console.log(reason);
    })

处理 promise 的异步情况

          处理异步调用的情况,就需要我们在 then 方法执行的时候,将成功 / 失败的回调函数保存起来,当异步任务结束触发 resolve、reject 的时候去再去执行成功/失败的回调函数


class iPromise {
  FILFULLD // --> 成功的回调函数
  REJECTED // --> 失败的回调函数
 
  resolve = (value) => {
    if (this.status != PENDING) {
      return
    }
    this.status = FULFILLED
    this.value = value
    // 如果有这个函数就执行它, 并传入成功的值
    this.FILFULLD && this.FILFULLD(this.value)
  }

  reject = (reason) => {
    if (this.status != PENDING) {
      return
    }
    this.status = REJECTED
    this.reason = reason
    // 如果有这个函数就执行它, 并传入失败的原因
    this.REJECTED && this.REJECTED(this.reason)
  }

// 判断当前执行状态是成功还是失败, 并调用对应的回调函数
  then(successCallback, errorCallback) {
    // 将成功/失败的回调函数保存到promise的原型上
    this.FILFULLD = successCallback
    this.REJECTED = errorCallback
    if (this.status == FULFILLED) {
      successCallback(this.value)
    } else if (this.status == REJECTED) {
      errorCallback(this.reason)
    }
  }
}

简易的完整版本

// 保存Promise的三个状态, 以便后续调用
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class iPromise {

  constructor(callback) {
    // 接收执行外部传入的匿名函数
    callback(this.resolve, this.reject)
  }

  value = null // --> 成功的值
  status = PENDING // --> promise声明时默认为pending(执行中)的状态
  reason = null // --> 失败的原因
  FILFULLD
  REJECTED
 
  resolve = (value) => {
    if (this.status != PENDING) {
      return
    }
    this.status = FULFILLED
    this.value = value
    this.FILFULLD && this.FILFULLD(this.value)
  }

  reject = (reason) => {
    if (this.status != PENDING) {
      return
    }
    this.status = REJECTED
    this.reason = reason
    this.REJECTED && this.REJECTED(this.reason)
  }
// 判断当前执行状态是成功还是失败, 并调用对应的回调函数
  then(successCallback, errorCallback) {
    this.FILFULLD = successCallback
    this.REJECTED = errorCallback
    if (this.status == FULFILLED) {
      successCallback(this.value)
    } else if (this.status == REJECTED) {
      errorCallback(this.reason)
    }
  }
}

处理异步情况之后的用法

        这里使用 setTimeout 来模拟了一下异步的情况

let promise = new iPromise((resolve, reject) => {
      setTimeout(() => {
        resolve('new promise')
      }, 1000)
      // reject('reaspn')
    })

    promise.then(res => {
      console.log(res); // new promise
    }, reason => {
      console.log(reason);
    })

到这里本章节的简易版本的 Promise 就基本可以实现了, 当然这也只是一部分, 后面将逐步剖析 Promise 的后续操作

  1. 处理 Promise.then 方法链式调用识别 Promise 对象
  2. 处理函数执行的异常情况
  3. 实现 Promise.all 的静态方法
  4. 实现 Promise.finally 的静态方法
  5. 实现 Promise.resolve 的静态方法
  6. 实现 Promise.catch 的静态方法

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值