https://segmentfault.com/a/1190000000684654

What?

PromiseCommonJS的规范之一,拥有resolverejectdonefailthen等方法,能够帮助我们控制代码的流程,避免函数的多层嵌套。如今异步在web开发中越来越重要,对于开发人员来说,这种非线性执行的编程会让开发者觉得难以掌控,而Promise可以让我们更好地掌控代码的执行流程,jQuery等流行的js库都已经实现了这个对象,年底即将发布的ES6也将原生实现Promise

Why

想象这样一个场景,两个异步请求,第二个需要用到第一个请求成功的数据,那么我们代码可以这样写

    ajax({
url: url1,
success: function(data) {
ajax({
url: url2,
data: data,
success: function() {
}
});
}
});

如果继续下去在回调函数中进行下一步操作,嵌套的层数会越来越多。我们可以进行适当的改进,把回调函数写到外面

    function A() {
ajax({
url: url1,
success: function(data) {
B(data);
}
});
}
function B(data) {
ajax({
url: url2,
success: function(data) {
......
}
});
}

即使是改写成这样,代码还是不够直观,但是如果有了Promise对象,代码就可以写得非常清晰,一目了然,请看

new Promise(A).done(B);

这样函数B就不用写在A的回调中了

How

目前的ES标准中还未支持Promise对象,那么我们就自己动手,丰衣足食吧。思路大致是这样的,用2个数组(doneListfailList)分别存储成功时的回调函数队列和失败时的回调队列

  • state: 当前执行状态,有pendingresolvedrejected3种取值

  • done: 向doneList中添加一个成功回调函数

  • fail: 向failList中添加一个失败回调函数

  • then: 分别向doneListfailList中添加回调函数

  • always: 添加一个无论成功还是失败都会调用的回调函数

  • resolve: 将状态更改为resolved,并触发绑定的所有成功的回调函数

  • reject: 将状态更改为rejected,并触发绑定的所有失败的回调函数

  • when: 参数是多个异步或者延迟函数,返回值是一个Promise兑现,当所有函数都执行成功的时候执行该对象的resolve方法,反之执行该对象的reject方法
    下面是我的具体实现过程:

var Promise = function() {
this.doneList = [];
this.failList = [];
this.state = 'pending';
}; Promise.prototype = {
constructor: 'Promise',
resolve: function() {
this.state = 'resolved';
var list = this.doneList;
for(var i = 0, len = list.length; i < len; i++) {
list[0].call(this);
list.shift();
}
},
reject: function() {
this.state = 'rejected';
var list = this.failList;
for(var i = 0, len = list.length; i < len; i++){
list[0].call(this);
list.shift();
}
},
done: function(func) {
if(typeof func === 'function') {
this.doneList.push(func);
}
return this;
},
fail: function(func) {
if(typeof func === 'function') {
this.failList.push(func);
}
return this;
},
then: function(doneFn, failFn) {
this.done(doneFn).fail(failFn);
return this;
},
always: function(fn) {
this.done(fn).fail(fn);
return this;
}
}; function when() {
var p = new Promise();
var success = true;
var len = arguments.length;
for(var i = 0; i < len; i++) {
if(!(arguments[i] instanceof Promise)) {
return false;
}
else {
arguments[i].always(function() {
if(this.state != 'resolved'){
success = false;
}
len--;
if(len == 0) {
success ? p.resolve() : p.reject();
}
});
}
}
return p;
}

Improve

目前只是实现了Promise的基础功能,但仍然还有无法处理的情况,例如要实现3个或3个以上的异步请求的串行,目前我的Promise没有办法支持new Promise(A).then(B).then(C)这样的形式,jQuery在1.7的版本中为Deferred(Promise)对象实现了pipe函数,可以通过这个函数实现上述功能,代码为$.Deferred(A).pipe(B).then(C),我尝试去读了jQuery这部分的代码,但是没能读懂,希望有大神能够给一些实现思路

浅谈Javascript中Promise对象的实现的更多相关文章

  1. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

  2. 浅谈JavaScript中的null和undefined

    浅谈JavaScript中的null和undefined null null是JavaScript中的关键字,表示一个特殊值,常用来描述"空值". 对null进行typeof类型运 ...

  3. 浅谈JavaScript中的正则表达式(适用初学者观看)

    浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...

  4. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  5. 浅谈Java中的对象和对象引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  6. 浅谈JavaScript中的Ajax

    引言 作为一名WEB开发者,我想Ajax技术是一定需要掌握的.你也许平时没有使用JavaScript真正的写过Ajax.但是你一定使用过JQuery里面的相关函数来进行异步调用.今天我们就来介绍下原生 ...

  7. 通过一道笔试题浅谈javascript中的promise对象

    因为前几天做了一个promise对象捕获错误的面试题目,所以这几天又重温了一下promise对象.现在借这道题来分享下一些很基础的知识点. 下面是一个面试题目,三个promise对象捕获错误的例子,返 ...

  8. 浅谈JavaScript中的内存管理

    一门语言的内存存储方式是我们学习他必须要了解的,接下来让我浅谈一下自己对他的认识. 首先说,JavaScript中的变量包含两种两种类型: 1)值类型或基本类型:undefined.null.numb ...

  9. 浅谈JavaScript中闭包

    引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...

随机推荐

  1. C#学习笔记---协变和逆变

    http://www.cnblogs.com/alphafly/p/4048608.html 协变是指方法能从委托的返回类型派生的一个类型. 逆变之方法获取的参数可以是委托参数类型的基类.

  2. Delphi多线程开发注意事项

    Q1: 多线程中需避免多个线程同时向全局变量进行写入操作,导致访问冲突问题. A1:  可以通过使用加锁机制(比如:临界区.互斥.信号量)解决此问题. Q2:多线程中对于结构体和CLASS类型的全局变 ...

  3. PHP商品秒杀计时实现(解决大流量方案)

    PHP商品秒杀功能我们多半以整点或时间点为例子,这样对于php来说处理不复杂,但有一个问题就是如果流量大要如何来处理,下面我们一起来看看解决办法. 要求要有小时分钟秒的实时倒计时的显示,用户端修改日期 ...

  4. phpcms v9网站搬家更换域名的方法

    PHPCMS 是国内领先的网站管理系统,同时也是一个开源的PHP开发框架. 本文介绍phpcms v9网站搬家更换域名的方法. 1.在新的主机空间把phpcms安装好. 新安装的版本一定要和准备搬迁的 ...

  5. gnuplot安装问题(set terminal "unknown")

    今天在系统同上要装个gnuplot,原来用的都是拷好的虚拟机.这也是第一次装.本来以为分分钟的事,却不料遇到不少麻烦.记录一下,供大家参考 一,快速开始安装 ubuntu下那自然是: sudo apt ...

  6. 关于RTP负载类型及时间戳介绍

    转自:http://www.360doc.com/content/11/1018/13/1016783_157133781.shtml 首 先,看RTP协议包头的格式: 前12个字节在每一个RTP p ...

  7. 5.linux内核模块基础,内核模块学习

    linux内核模块基础 一.定义 Linux 内核的整体结构非常庞大,其包含的组件也非常多,如何使用这些组件呢: 方法 1:把所有的组件都编译进内核文件,即:zImage 或 bzImage,但这样会 ...

  8. MySQL的中文编码问题

    创建表格时,怎么让表格显示中文?注意:不区分大小写 mysql> ALTER TABLE 表格的名字 CONVERT TO CHARACTER SET UTF8; 怎么让默认的数据库支持中文字符 ...

  9. Java可变参数讲解

    如果实现的多个方法,这些方法里面逻辑基本相同,唯一不同的是传递的参数的个数,可以使用可变参数可变参数的定义方法 数据类型...数组的名称,这个数组存储传递过来的参数,类似JavaScript注意点:  ...

  10. phpstudy配置ssl

    https://yunpan.cn/cPEyzVycbkiE3 (提取码:03aa) 1.重写规则:http://www.cnphp.info/htaccess-rewrite.html 2.相关文档 ...