JS手写一个自定义Promise操作示例


Posted in Javascript onMarch 16, 2020

本文实例讲述了JS手写一个自定义Promise操作。分享给大家供大家参考,具体如下:

经常在面试题中会看到,让你实现一个Promsie,或者问你实现Promise的原理,所以今天就尝试利用class类的形式来实现一个Promise

为了不与原生的Promise命名冲突,这里就简单命名为MyPromise.

class MyPromise {
 constructor(executor) {
  let _this = this
  this.state = 'pending' // 当前状态
  this.value = undefined // 存储成功的值
  this.reason = undefined // 存储失败的值
  // 利用发布订阅模式,让Promise支持异步
  this.onFulfilledFunc = [] // 存储成功的回调
  this.onRejectedFunc = [] // 存储失败的回调

  function resolve (value) {
   // Promise对象已经由pending状态改变为了成功态(resolved)或是失败态(rejected)就不能再次更改状态了。因此我们在更新状态时要判断,如果当前状态是pending(等待态)才可更新
   if (_this.state === 'pending') {
    _this.value = value
    //依次执行成功回调
    _this.onFulfilledFunc.forEach(fn => fn(value))
    _this.state = 'resolved'
   }
  }

  function reject (reason) {
   // Promise对象已经由pending状态改变为了成功态(resolved)或是失败态(rejected)就不能再次更改状态了。因此我们在更新状态时要判断,如果当前状态是pending(等待态)才可更新
   if (_this.state === 'pending') {
    _this.reason = reason
    //依次执行失败回调
    _this.onRejectedFunc.forEach(fn => fn(reason))
    _this.state = 'rejected'
   }
  }

  try {
   // 当实例化Promise时,构造函数中就要马上调用传入的executor函数执行
   executor(resolve, reject)
  } catch (error) {
   reject(error)
  }
 }
 _resolvePromise (promise2, x, resolve, reject) {
  // 如果返回了自己的Promise对象,状态永远为等待态(pending),再也无法成为resolved或是rejected,程序会死掉,因此首先要处理它
  if (promise2 === x) {
   reject(new TypeError('Promise存在循环引用'))
  }
  if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
   // x可能是一个promise
   try {
    let then = x.then
    if (typeof then === 'function') {
     then.call(x, (y) => {
      _resolvePromise(promise2, y, resolve, reject)
     })
    } else {
     resolve(x)
    }
   } catch (err) {
    reject(err)
   }
  } else {
   //否则是个普通值
   resolve(x)
  }
 }
 then (onFulfilled, onRejected) {
  let promise2
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (val) { return val }
  onRejected = typeof onRejected === 'function' ? onRejected : function (reason) { throw reason }

  if (this.state === 'resolved') {
   promise2 = new MyPromise((resolve, reject) => {
    setTimeout(() => {
     try {
      let x = onFulfilled(this.value)
      this._resolvePromise(promise2, x, resolve, reject)
     } catch (error) {
      reject(error)
     }
    }, 0);
   })
  }

  if (this.state === 'rejected') {
   promise2 = new MyPromise((resolve, reject) => {
    setTimeout(() => {
     try {
      let x = onRejected(this.reason)
      this._resolvePromise(promise2, x, resolve, reject)
     } catch (error) {
      reject(error)
     }
    }, 0);
   })
  }

  if (this.state === 'pending') {
   promise2 = new MyPromise((resolve, reject) => {
    this.onFulfilledFunc.push(() => {
     setTimeout(() => {
      try {
       let x = onFulfilled(this.value)
       this._resolvePromise(promise2, x, resolve, reject)
      } catch (error) {
       reject(error)
      }
     }, 0);
    })

    this.onRejectedFunc.push(() => {
     setTimeout(() => {
      try {
       let x = onRejected(this.reason)
       this._resolvePromise(promise2, x, resolve, reject)
      } catch (error) {
       reject(error)
      }
     }, 0);
    })
   })
  }

  return promise2
 }
}

运行测试:

var promise = new MyPromise((resolve, reject) => {
 console.log(1)
 setTimeout(() => {
  resolve(2)
 }, 1000);
 console.log(3)
}).then(value => console.log(value))

结果真香:

JS手写一个自定义Promise操作示例

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
百度 popup.js 完美修正版非常的不错 脚本之家推荐
Apr 17 Javascript
关于jQuery中的each方法(jQuery到底干了什么)
Mar 05 Javascript
关于javaScript注册click事件传递参数的不成功问题
Jul 18 Javascript
JavaScript实现广告的关闭与显示效果实例
Jul 02 Javascript
JS+CSS实现带有碰撞缓冲效果的竖向导航条代码
Sep 15 Javascript
全系IE支持Bootstrap的解决方法
Oct 19 Javascript
基于ExtJs在页面上window再调用Window的事件处理方法
Jul 26 Javascript
webpack2.0配置postcss-loader的方法
Aug 17 Javascript
实现两个文本框同时输入的实例
Sep 25 Javascript
vue视频播放插件vue-video-player的具体使用方法
Nov 08 Javascript
JavaScript实现京东放大镜效果
Dec 03 Javascript
TypeScript 内置高级类型编程示例
Sep 23 Javascript
JS函数参数的传递与同名参数实例分析
Mar 16 #Javascript
vue css 引入asstes中的图片无法显示的四种解决方法
Mar 16 #Javascript
JS函数本身的作用域实例分析
Mar 16 #Javascript
JavaScript实现tab栏切换效果
Mar 16 #Javascript
vue-cli3使用mock数据的方法分析
Mar 16 #Javascript
vue-cli3.0实现一个多页面应用的历奇经历记录总结
Mar 16 #Javascript
vue从零实现一个消息通知组件的方法详解
Mar 16 #Javascript
You might like
url decode problem 解决方法
2011/12/26 PHP
解决CodeIgniter伪静态失效
2014/06/09 PHP
Js从头学起(基本数据类型和引用类型的参数传递详细分析)
2012/02/16 Javascript
javascript折半查找详解
2015/01/26 Javascript
在JavaScript中操作时间之getUTCDate()方法的使用
2015/06/10 Javascript
js 上传文件预览的简单实例
2016/08/16 Javascript
JS制作适用于手机和电脑的通知信息效果
2016/10/28 Javascript
使用snowfall.jquery.js实现爱心满屏飞的效果
2017/01/05 Javascript
JS查找字符串中出现最多的字符及个数统计
2017/02/04 Javascript
JavaScript实现公历转农历功能示例
2017/02/13 Javascript
在使用JSON格式处理数据时应该注意的问题小结
2017/05/20 Javascript
详解在Vue中有条件地使用CSS类
2017/09/30 Javascript
EasyUI实现下拉框多选功能
2017/11/07 Javascript
vue2.0+vue-dplayer实现hls播放的示例
2018/03/02 Javascript
react router4+redux实现路由权限控制的方法
2018/05/03 Javascript
微信小程序自定义对话框弹出和隐藏动画
2018/07/19 Javascript
深入理解JavaScript 中的匿名函数((function() {})();)与变量的作用域
2018/08/28 Javascript
vue实现重置表单信息为空的方法
2018/09/29 Javascript
原生JavaScript实现拖动校验功能
2020/09/29 Javascript
[01:23:45]DOTA2-DPC中国联赛 正赛 CDEC vs Dragon BO3 第一场 1月22日
2021/03/11 DOTA
Python对列表排序的方法实例分析
2015/05/16 Python
基于python中staticmethod和classmethod的区别(详解)
2017/10/24 Python
Python wxPython库使用wx.ListBox创建列表框示例
2018/09/03 Python
python调用opencv实现猫脸检测功能
2019/01/15 Python
python3.6下Numpy库下载与安装图文教程
2019/04/02 Python
DjangoWeb使用Datatable进行后端分页的实现
2020/05/18 Python
澳大利亚连衣裙和女装在线:Esther
2017/11/11 全球购物
销售文员岗位职责
2013/11/29 职场文书
一分钟演讲稿
2014/04/30 职场文书
党在我心中演讲稿
2014/09/02 职场文书
学位证书委托书
2014/09/30 职场文书
2014年初三班主任工作总结
2014/12/05 职场文书
干部个人考察材料
2014/12/24 职场文书
干部年终考核评语
2015/01/04 职场文书
周一早安温馨问候祝福语!
2019/07/15 职场文书
坚持不是死撑,更重要的是心态
2019/08/19 职场文书