Promise原理

参考https://github.com/chunpu/promise/blob/master/promise.js

个人认为原博的实现有点问题 在next函数的实现上, 会导致无限的调用

看看一般Promise的用法

promise = new Promise(function(resolve, reject) {
//...
resolve(1);
//...
})
.then(function(val){}, functioin(err){})
.then(function(val){}, functioin(err){})

显然要实现的功能是这样的

Promise对象有then方法

Promise对象接受一个参数fn(resolve, reject)

Promise可以连续的then调用

function Promise(resolver) {
var queue = [];//链式调用数组
resolver(resolve, reject); //state 0 是resolve
function next(state, val){
var arr;
if(arr = queue.shift()){
arr[state](val);
}
} function resolve(x){
next(0, x)
}
function reject(reason){
next(1, reason);
} //Promise最明显的特征 是可以then then接收两个参数
//then就是将传入的函数放入队列中
this.then = function(resolve, reject){
queue.push([resolve, reject]); //resovle reject 这两个参数也都是函数
}
} var p = new Promise(function(resolve){
resolve('ok')
}) p.then(function(x){
console.log(x);
})

有个问题 那就是创建一个Promise对象的时候就调用了 resolver(resolve, reject); 也就是调用了resolve('ok') 也就是调用了next 也就是使queue函数出队列并执行

但是这个时候 queue 还没有push任何值 执行不能继续 毕竟这个是在Promise对象完成创建之后才调用then

为了使next在then中的函数全部进到队列之后再执行 用一个setTimeout把 next中的逻辑包裹

function Promise(resolver) {
var queue = [];
resolver(resolve, reject); function next(state, val){
var arr;
//为了使resolve晚于 then 执行 暂时用一个setTimeout
setTimeout(function(){
if(arr = queue.shift()){
arr[state](val);
}
}, 0);
} function resolve(x){
next(0, x);
}
function reject(reason){
next(1, reason);
} this.then = function(resolve, reject){
queue.push([resolve, reject]);
}
} var p = new Promise(function(resolve){
setTimeout(function(){
resolve('ok')
},1200);
}).then(function(data){
console.log(data);
})

不过我们知在一个then中 return 可能不仅仅是一个简单地的value , 有可能再次返回一个Promise对象 而下一个then中resolve函数的的data是这个Promise对象resolve()的值

听起来很复杂 针对return一个Promise对象的情况 就是调用这个对象的then

然后再次进入next 而next的参数就是返回的Promise对象的resolve的值

function Promise(resolver) {
var queue = []; //链式调用数组
resolver(resolve, reject); //state 0 是resolve
function next(state, val) {
var arr;
var chainRs;
setTimeout(function() {
if (arr = queue.shift()) {
chainRs = arr[state](val);
if(!chainRs) return;
//某一个resolve函数返回的又是一个Promise对象
if (chainRs && typeof chainRs.then == 'function') {
chainRs.then(resolve, reject);
} else {
//resolve函数返回一个普通的值
resolve(chainRs) //.then(resolve, reject);
}
}
}, 0);
} function resolve(x) {
next(0, x);
} function reject(reason) {
next(1, reason);
}
//Promise最明显的特征 是可以then then接收两个参数
//then就是将传入的函数放入队列中
this.then = function(resolve, reject) {
queue.push([resolve, reject]); //resovle reject 这两个参数也都是函数
return this;
}
}
Promise.resolve = Promise.cast = function(x) {
return new Promise(function(resolve) {
resolve(x);
})
}

测试

var p = new Promise(function(resolve) {
setTimeout(function() {
resolve('ok')
}, 1200);
}).then(function(data) {
console.log(data);
// return 555;
return new Promise(function(resolve){
setTimeout(function(){
resolve('wahaha');
}, 2200);
})
})
.then(function(data) {
console.log('2nd then', data);
return 666;
})
.then(function(data) {
console.log('3rd then', data);
});

完善 增加Promise.all() Promise.resolve()

Promise.resolve = Promise.cast = function(x) {
return new Promise(function(resolve) {
resolve(x);
})
} Promise.all = function(promises){
var len = promises.length;
var results = [];
return new Promise(function(resolve){
promises.forEach(function(p, i){
p.then(function(data){
results[i] = data;
len--;
if(len == 0){
resolve(results);
}
}, function(err){
console.log(err);
});
});
});
} //================================= Promise.resolve(999)
.then(function(data){
console.log(data);
return new Promise(function(resolve, reject){
// resolve('xixi');
reject('xixi');
})
}).then(function(data){
console.log(data);
},function(err){
console.log(err);
}) Promise.all([
new Promise(function(resolve){
setTimeout(function(){
resolve(111);
}, 1000); }),
new Promise(function(resolve){
resolve(222);
}) ]).then(function(results){
console.log(results);
})

Promise原理 && 简单实现的更多相关文章

  1. promise原理

      简介 Promise 对象用于延迟(deferred) 计算和异步(asynchronous )计算.一个Promise对象代表着一个还未完成,但预期将来会完成的操作.Promise 对象是一个返 ...

  2. 这一次,彻底弄懂 Promise 原理

    作者声明 本人将迁移至个人公众号「前端Q」及「掘金」平台写文章.博客园的文章将不再及时更新发布.欢迎大家关注公众号「前端Q」及我的掘金主页:https://juejin.im/user/5874526 ...

  3. wp7之换肤原理简单分析

    wp7之换肤原理简单分析 纠结很久...感觉勉强过得去啦.还望各位大牛指点江山 百度找到这篇参考文章http://www.cnblogs.com/sonyye/archive/2012/03/12/2 ...

  4. jQuery插件实现的方法和原理简单说明

    下文来自 http://www.itzhai.com/jquery-plug-ins-to-achieve-the-methods-and-principles-of-simple-instructi ...

  5. Promise 原理

    异步:可同时好几件事,互不影响: 同步:按循序一件一件.... 异步好多缺点:.... promise就是解决异步计算的这些缺点的,主要用于: 1.异步计算: 2.可以将异步操作队列化  按期望的顺序 ...

  6. Promise的简单用法

    众所周知的,Javascript是一种单线程的语言,所有的代码必须按照所谓的“自上而下”的顺序来执行.本特性带来的问题就是,一些将来的.未知的操作,必须异步实现.本文将讨论一个比较常见的异步解决方案— ...

  7. LDAP服务器的概念和原理简单介绍

    LDAP服务器的概念和原理简单介绍 1. 目录服务 目录是一个为查询.浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好象Linux/Unix系统中的文件目录一样.目录数据库和关系数据库不 ...

  8. promise原理及使用方法

    Promise 的含义 所谓Promise ,简单说就是一个容器,里面保存着某个未来才回结束的事件(通常是一个异步操作)的结果.从语法上说,Promise是一个对象,从它可以获取异步操作的消息. re ...

  9. Docker系列之原理简单介绍

    目录 1.1.Docker架构简介 1.2.Docker 两个主要部件 1.3.虚拟机和Docker对比: 1.4.Docker内部结构 Docker系列之原理简单介绍 @ Docker是一个开源的应 ...

随机推荐

  1. Log4j.properties配置详细解读

    Log4j.properties配置 Log4j有三个主要的组件:Loggers(记录器),Appenders  (输出源)和Layouts(布局).这里可简单理解为日志类别,日志要输出的地方和日志以 ...

  2. mysql的分页存储过程,能够传出总记录数

    最近用mysql + asp.net来写网站,既然mysql已经支持存储过程了,那么像分页这么常用的东西,当然要用存储过程啦 不过在网上找了一些,发现都有一个特点——就是不能传出总记录数,干脆自己研究 ...

  3. 是一个IPV6地址

    每次在VS上调试,发现本机地址是 ::1 这种就不解.由于太忙而没关注,今天看了IPV6的文章才明白.原来这是个IPV6地址,也就是本机环回地址.以前是127.0.0.1,IPV4版本,而IPV6的就 ...

  4. JVM虚拟机选项:Xms Xmx PermSize MaxPermSize区别

    java虽然是自动回收内存,但是应用程序,尤其服务器程序最好根据业务情况指明内存分配限制.否则可能导致应用程序宕掉. 举例说明含义:-Xms128m 表示JVM Heap(堆内存)最小尺寸128MB, ...

  5. 程序A+B问题(一次输入和多次输入)

    这是早就会写的题,把它整理一下,比较容易. ➀一次输入数据,计算A+B   #include<stdio.h> #include<stdlib.h> int main() { ...

  6. LoadRunner 技巧之THML 与 URL两种录制模式分析

    Loadrunner的Virtual User Generator 提供人脚本的录制功能,对于初学者来说,这大大的降低了编写脚本的门槛,loadrunner提供两种录制脚本的方式:Html_based ...

  7. JIRA项目跟踪管理工具简介与安装

    1.什么是JIRA JIRA是Atlassian公司出品的项目与事务跟踪工具,被广泛应用于缺陷跟踪.客户服务.需求收集.流程审批.任务跟踪.项目跟踪和敏捷管理等工作领域. Atlassian2002年 ...

  8. relay 2015-02-05 21:00 27人阅读 评论(0) 收藏

    scanf函数是以在输入多个数值数据时,若格式控制串中没有非格式字符作输入数据之间的间隔,则可用空格,TAB或回车作间隔. C编译在碰到空格,TAB,回车或非法数据(如对"%d"输 ...

  9. 推荐一款JavaScript日历控件:kimsoft-jscalendar

    一.什么是 kimsoft-jscalendar     一个简洁的avaScript日历控件,可在Java Web项目,.NET Web 项目中使用 二.kimsoft-jscalendar 有什么 ...

  10. PHP出现Notice: unserialize() [function.unserialize]: Error at offset问题的解决方案

    有两个原因(据我所知)会导致这个问题: (1) 字符串本身的问题 (2)字符编码的问题. 你unserialize的字符串的编码和文件本身的编码不一致.将文件编码改成和字符串一样的编码.这种问题比较隐 ...