话不多说,直接上代码

通过ES5的模块化封装,向外暴露一个属性

(function(window){

  const PENDING = 'pending';

  const RESOLVED = 'fulfilled'

  const REJECTED = 'rejected'

  function MyPromise(excutor){

    const self = this;   //保存Promise对象,防止异步执行时,拿不到数据和方法,必要

    self.value = undefined;

    self.status = PENDING;

    self.callbacks = [] //当状态没有发生改变时,需要储存起回调函数, 在then方法中获取回调函数

    function resolve(value){

      self.value = value;

      self.status = RESOLVED;

      self.callbacks.map(cb => {

        setTimeout(() => { //定时器模拟异步执行,必须保证回调异步执行,否则顺序就乱了

           cb.onResolved(self.value)

        })

      }) //执行保存起来的成功回调函数

    }

     function reject(value){

      self.value = value;

      self.status = REJECTED ;

      self.callbacks.map(cb => {

        setTimeout(() => {

          cb.onRejected (self.value)

        })

      })//执行保存起来的失败的回调函数

    }

    try{   //若在执行器函数中主动抛出错误,需要捕获错误,并把状态更改为rejected

      excutor(resolve,reject)

    } catch (error){

      reject(error)

    }

  }

  MyPromise.prototype.then = function( onResolved,onRejected ){

    const self = this//保存当前的Promise对象

    return new Promise(resolve,reject){

      onResolved = onResolved === 'function' ? onResolved : v => v

      onRejected  = onRejected === 'function' ? onRejected :  error => {throw error}  //实现异常透传

      //判断当前的状态

      //假如Promise执行的异步任务,then方法是同步方法,那么当时Promise的状态为pending,所以不能执行回调,此时需要保存

      if(self.status === PENDING){

        // 这里只是把回调保存了起来,并没有改变当前的Promise对象,所以得进一步处理,处理和成功得处理类似

        self.callbacks.push({onResolved,onRejected})  //保存每一个then方法为一个对象,包含onResolved,onRejected两个函数

      } else if(self.status === RESOLVED){

        //1. 保证then中的回调异步执行,加一个setTimeout

        //2. 在onResolved中如果主动抛出错误,需要捕获错误

        //3. 根据Promise对象返回的结果,来决定下一个then中执行成功还是失败的回调

        //4. 如果上一个Promise返回的是一个值,如return 2,那么直接用resolve(2)执行

        //5. 如果上一个Promise返回的是一个promise对象,那么要通过promise.then 来获取promise的执行结果

        setTimeout(() => {

          try {

            const result = onResolved(self.value)

            if( result instanceof MyPromise){ //判断返回值是不是Promise对象

              //返回一个Promise对象

              result.then(

                value => {  //返回值是Promise对象,并且是成功的,那么就会执行这一个函数

                  resolve(self.value)

                }  

                error => {  //返回值是Promise对象,并且是失败的,那么就会执行这一个函数

                  rejecte(self.value)

                }

              )  

            }else {  //返回的不是一个Promise对象

               resolve(self.value)

            }

          } catch (error) {

             //与成功的处理一样,只需要更改一下回调函数,太长就不写了

          }

        })

      } else { //rejected状态}  

      }

    }

  window.MyPromise = MyPromise //向外暴露方法

})(window)

到这里就差不多写完简易的promise了,了解了原理也能更好的使用promise

欢迎指正,若有不清楚,也可评论指出

手写Promise简易版的更多相关文章

  1. 来,我们手写一个简易版的mock.js吧(模拟fetch && Ajax请求)

    预期的mock的使用方式 首先我们从使用的角度出发,思考编码过程 M1. 通过配置文件配置url和response M2. 自动检测环境为开发环境时启动Mock.js M3. mock代码能直接覆盖g ...

  2. 手写spring(简易版)

    本文版权归 远方的风lyh和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作,如有错误之处忘不吝批评指正! 理解Spring本质: 相信之前在使用spring的时候大家都配置web.x ...

  3. 手写一个简易版Tomcat

    前言 Tomcat Write MyTomcat Tomcat是非常流行的Web Server,它还是一个满足Servlet规范的容器.那么想一想,Tomcat和我们的Web应用是什么关系? 从感性上 ...

  4. 我手写的简易tomcat

    前述 自己手写的简易的tomcat,实现了tomcat的基本响应功能,项目代码已经上传到我的Github,刚刚开始学习这里,当前还存在很多问题 项目简述及代码 当我们的Web运行的时候,从浏览器发出的 ...

  5. 手写Promise A+ 规范

    基于ES6语法手写promise A+ 规范,源码实现 class Promise { constructor(excutorCallBack) { this.status = 'pending'; ...

  6. 手写promise

    写在前面: 在目前的前端分开中,我们对于异步方法的使用越来越频繁,那么如果处理异步方法的返回结果,如果优雅的进行异步处理对于一个合格的前端开发者而言就显得尤为重要,其中在面试中被问道最多的就是对Pro ...

  7. 手写 Promise

    在上一章节中我们了解了 Promise 的一些易错点,在这一章节中,我们会通过手写一个符合 Promise/A+ 规范的 Promise 来深入理解它,并且手写 Promise 也是一道大厂常考题,在 ...

  8. 手写Promise看着一篇就足够了

    目录 概要 博客思路 API的特性与手写源码 构造函数 then catch Promise.resolved Promise.rejected Promise.all Promise.race 概要 ...

  9. 手写Promise中then方法返回的结果或者规律

    1. Promise中then()方法返回来的结果或者规律 我们知道 promise 的 then 方法返回来的结果值[result]是由: 它指定的回调函数的结果决定的 2.比如说下面这一段代码 l ...

随机推荐

  1. mongoose.model第三个参数的问题

    这个是个好问题,之前按照教程做的数据库没有问题,现在自己从新做出现了问题.还好之前有无意中接触了这个知识点,不然感觉真的很难解决. 在检查完所有东西都没错的时候(前端传给req的数据正常,与数据库相符 ...

  2. java实现经典坦克大战及源代码下载

    坦克大战源码 (点击即可下载) 链接:https://pan.baidu.com/s/1m9aVheaquwxGKjYQrb72AA 提取码:j8dr see you ! 觉得有用的话点个赞再走

  3. P5468 [NOI2019]回家路线 斜率优化 dp

    LINK:回家路线 (文化课 oi 双爆炸 对 没学上的就是我.(我错了不该这么丧的. 不过还能苟住一段时间.当然是去打NOI了 这道题去年同步赛的时候做过.不过这里再次提醒自己要认真仔细的看题目 不 ...

  4. day3. 六大标准数据类型的类型转换

    一.强制类型转换Number 1.int  强制转换成整型 var1 = 13 var2 = 13.789 var3 = True var4 = 5-7j var5 = "" va ...

  5. Spring的事务抽象

    Spring提供了一致的事务管理抽象,该抽象能实现为不同的事务API提供一致的编程模型.无视我们使用jdbc.hibernate.mybatis哪种方式来操作数据,无视事务是jta事务还是jdbc事务 ...

  6. What is 测试金字塔?

    我的女朋友是一名测试工程师,但她之前却不知道测试金字塔的概念,为此我曾经在家里的白板上画了一个图一层一层给她讲解过.我和同事在给团队面试测试和开发岗位时,也会必问到这个问题,想到可能有很多开发童鞋都不 ...

  7. 通过源码分析Java开源任务调度框架Quartz的主要流程

    通过源码分析Java开源任务调度框架Quartz的主要流程 从使用效果.调用链路跟踪.E-R图.循环调度逻辑几个方面分析Quartz. github项目地址: https://github.com/t ...

  8. 浅谈js数组中的length属性

    前言 一位正在学习前端的菜鸟,虽菜,但还未放弃. 内容 首先,我们都知道每个数组都有一个length属性 这个length属性一般我们用来循环遍历的约束,一般我们都会把他认为是该数组里面有几个元素这个 ...

  9. Mybatis 的连接池技术

    我们在前面的 WEB 课程中也学习过类似的连接池技术,而在 Mybatis 中也有连接池技术,但是它采用的是自 己的连接池技术.在 Mybatis 的 SqlMapConfig.xml 配置文件中,通 ...

  10. Kaggle-pandas(4)

    Grouping-and-sorting 教程 映射使我们可以一次将整个列中的数据转换为DataFrame或Series中的一个值. 但是,通常我们希望对数据进行分组,然后对数据所在的组进行特定的操作 ...