Promise 原理探究及其简单实现
可移步 http://donglegend.com/2016/09/11/promise%E5%8E%9F%E7%90%86%E6%8E%A2%E7%A9%B6/ 观看
Promise是个什么玩意,大家都知道,度娘告诉我,以同步方式书写异步,解决回调地狱。。。
状态机
早闻Promise的大名,简单介绍,根据状态改变来执行相应处理函数。
Promise的状态极其简单,只有 “pending”, “resolved”, “rejected”三种状态
然后就是如何实现的问题,最关键的当然是监听到状态的更新,然后才能做出回应,那么如何知道状态变了呢?
最初单纯的我开了一个脑洞,有以下想法:
- 写一个定时器不断查询状态值,如果有变化,那么执行回调
- 利用ES5的 Object.defineProperty(obj, prop, descriptor)来追踪状态变化。
- 直接修改状态为指定值,然后接着执行回调
呜呜呜,有时候总会犯傻不是,上面第一种维护一个定时器,效率低下;第二种把状态变得很麻烦和复杂;
其实很多事情之所以复杂,是因为我们想的太多。
Promise根本没那么复杂,就三个状态,搞毛线定时器,状态跟踪。
利用观察者模式,只需要通过特定书写方式注册对应状态的事件处理函数,然后更新状态,调用注册过的处理函数即可。这个特定方式就是 then ,done ,fail, always…等方法;更新状态触发时机就是resolve, reject方法。
简单实现
理论分析:
- 写一个类对象,维护一个 state,值有3种:”pending”, “resolved”, “rejected”
- 通过then done fail always方法注册回调处理函数
- 通过resolve reject分别更新对应状态,并且调用注册函数
代码如下:
- /**
- * [3种状态]
- * @type {String}
- */
- var PENDING = "pending";
- var RESOLVED = "resolved";
- var REJECTED = "rejected";
- /**
- * [Promise类实现]
- * 构造函数传入一个fn,有两个参数,resolve:成功回调; reject:失败回调;
- * state: 状态存储
- * doneList: 成功处理函数列表
- * failList: 失败处理函数列表
- * done: 注册成功处理函数
- * fail: 注册失败处理函数
- * then: 同时注册成功和失败处理函数
- * always: 一个处理注册到成功和失败,都会调用
- * resolve: 更新state为:RESOLVED,并且执行成功处理队列
- * reject: 更新state为:REJECTED,并且执行失败处理队列
- */
- var Promise = (function (){
- function Promise(fn){
- this.state = PENDING;
- this.doneList = [];
- this.failList = [];
- this.fn = fn;
- this.fn(this.resolve.bind(this), this.reject.bind(this))
- }
- var p = {
- done: function (cb){
- if(typeof cb == "function")
- this.doneList.push(cb)
- return this;
- },
- fail: function(cb){
- if(typeof cb == "function")
- this.failList.push(cb);
- return this;
- },
- then: function(success, fail){
- this.done(success || noop).fail(fail || noop)
- return this;
- },
- always: function(cb){
- this.done(cb).fail(cb)
- return this;
- },
- resolve: function(){
- this.state = RESOLVED;
- var lists = this.doneList;
- for(var i = 0, len = lists.length; i<len; i++){
- lists[0].apply(this, arguments);
- lists.shift();
- }
- return this;
- },
- reject: function(){
- this.state = REJECTED;
- var lists = this.failList;
- for(var i = 0, len = lists.length; i<len; i++){
- lists[0].apply(this, arguments);
- lists.shift();
- }
- return this;
- }
- }
- for(var k in p){
- Promise.prototype[k] = p[k]
- }
- return Promise;
- })();
- function noop(){}
使用方式,请到https://github.com/donglegend/MyPromise下载使用
源码下载
Promise 原理探究及其简单实现的更多相关文章
- Promise原理探究及实现
前言 作为ES6处理异步操作的新规范,Promise一经出现就广受欢迎.面试中也是如此,当然此时对前端的要求就不仅仅局限会用这个阶段了.下面就一起看下Promise相关的内容. Promise用法及实 ...
- Promise学习探究
学习熟知吧,原理还是继续吧 例子1: var isGeted; function getRet(){ return new Promise(function(resolve, reject) { // ...
- Promise原理 && 简单实现
Promise原理 参考https://github.com/chunpu/promise/blob/master/promise.js 个人认为原博的实现有点问题 在next函数的实现上, 会导致无 ...
- [原] KVM 虚拟化原理探究(6)— 块设备IO虚拟化
KVM 虚拟化原理探究(6)- 块设备IO虚拟化 标签(空格分隔): KVM [toc] 块设备IO虚拟化简介 上一篇文章讲到了网络IO虚拟化,作为另外一个重要的虚拟化资源,块设备IO的虚拟化也是同样 ...
- [原] KVM 虚拟化原理探究(4)— 内存虚拟化
KVM 虚拟化原理探究(4)- 内存虚拟化 标签(空格分隔): KVM 内存虚拟化简介 前一章介绍了CPU虚拟化的内容,这一章介绍一下KVM的内存虚拟化原理.可以说内存是除了CPU外最重要的组件,Gu ...
- [原] KVM 虚拟化原理探究(2)— QEMU启动过程
KVM 虚拟化原理探究- QEMU启动过程 标签(空格分隔): KVM [TOC] 虚拟机启动过程 第一步,获取到kvm句柄 kvmfd = open("/dev/kvm", O_ ...
- 弱类型变量原理探究(转载 http://www.csdn.net/article/2014-09-15/2821685-exploring-of-the-php)
N首页> 云计算 [问底]王帅:深入PHP内核(一)——弱类型变量原理探究 发表于2014-09-19 09:00| 13055次阅读| 来源CSDN| 36 条评论| 作者王帅 问底PHP王帅 ...
- promise原理
简介 Promise 对象用于延迟(deferred) 计算和异步(asynchronous )计算.一个Promise对象代表着一个还未完成,但预期将来会完成的操作.Promise 对象是一个返 ...
- 这一次,彻底弄懂 Promise 原理
作者声明 本人将迁移至个人公众号「前端Q」及「掘金」平台写文章.博客园的文章将不再及时更新发布.欢迎大家关注公众号「前端Q」及我的掘金主页:https://juejin.im/user/5874526 ...
随机推荐
- iOS - NSError用法规范
iphone跬步之--错误信息 NSError 一.获取系统的错误信息 比如移动文件时,获取文件操作错误: NSError *e = nil;[[NSFileManager defaultMana ...
- 算法与设计模式系列1之Python实现常见算法
preface 常见的算法包括: 递归算法 二分法查找算法 冒泡算法 插入排序 快速排序 二叉树排序 下面就开始挨个挨个的说说原理,然后用Python去实现: 递归算法 一个函数(或者程序)直接或者间 ...
- matlab和C/C++混合编程--调用opencv
最近的我们已经将整个项目搭起来了,项目比较复杂.由于我们做的是检索系统,所以我们用asp.net(c#)做了网页,但是算法的实现是在matlab下,所以我们不得不用matlab生成动态链接库dll,然 ...
- 日志分析 第六章 安装elasticsearch
在这里,以两台es集群为例. es集群健康状况有三种状态,这里我们搭建的es集群,只要两台不同时挂掉,数据不会丢失. green 所有主要分片和复制分片都可用 yellow 所有主要分片可用,但不是所 ...
- phpcms后台获取当前登录账号的数据
$amdinid=$_SESSION['userid'];$infoadmin=$this->admin->get_one(array('userid'=>$amdinid)); v ...
- php常用时间戳记录
<?php echo '<br/>'; //php获取今日开始时间戳和结束时间戳 echo "今天"; echo '<br/>'; $beginTod ...
- guid正则表达
a-fA-F0-9 加上下划线 _ 可以用 \w 来代替. ^\w{8}-(\w{4}-){3}\w{12}$ 如果不可以用下划线, 0-9 用 \d 代替 a-fA-F 就用其中一个 a-f,然后匹 ...
- python- shutil 高级文件操作
简介 shutil模块提供了大量的文件的高级操作.特别针对文件拷贝和删除,主要功能为目录和文件操作以及压缩操作.对单个文件的操作也可参见os模块. 拷贝文件 shutil.copyfile(src, ...
- MongoDB 3.0.6 安装 增删改查
下载 安装包MSI http://yunpan.cn/cmhHdTPkXZRM2 访问密码 9b6c 上边提供的是 MongoDB 3.0.6 64Bit 的安装包 安装 如果不想直接安装在C盘.. ...
- linux下代替system的基于管道的popen和pclose函数
linux下使用system需要谨慎,那么代替它的方法是什么呢? 标准I/O函数库提供了popen函数,它启动另外一个进程去执行一个shell命令行. 这里我们称调用popen的进程为父进程,由pop ...