简介

Promise 对象用于延迟(deferred) 计算和异步(asynchronous )计算。一个Promise对象代表着一个还未完成,但预期将来会完成的操作。Promise 对象是一个返回值的代理,这个返回值在promise对象创建时未必已知。它允许你为异步操作的成功或失败指定处理方法。 这使得异步方法可以像同步方法那样返回值:异步方法会返回一个包含了原返回值的 promise 对象来替代原返回值。

解决了什么问题及怎么使用

// 一个简单的示例 执行一个动画A,执行完之后再去执行另一个动画B
setTimeout(function(){
//A动画
console.log('A');
setTimeout(function() {
//B动画
console.log('B');
},)
},);
// 这里只有两个动画,如果有更多呢,就会看到一堆函数缩进

不难想象,如果依次有很多个动画,就会出现多重嵌套。代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理。

因为多个异步操作形成了强耦合,只要有一个操作需要修改,它的上层回调函数和下层回调函数,可能都要跟着修改。这种情况就称为回调函数地狱“(callback hell)。

Promise 对象就是为了解决这个问题而提出的。它不是新的语法功能,而是一种新的写法,允许将回调函数的嵌套,改成链式调用。

浏览器实现方式:可以在支持Promise的版本上运行

var p = new Promise(function (resolve, reject) {
setTimeout(function () {
// A动画
console.log('A');
resolve();
}, );
}); p.then(function () {
setTimeout(function () {
// B动画
console.log('B');
}, );
});

promise会让代码变得更容易维护,像写同步代码一样写异步代码。

promise原理

其实,promise就是三个状态。利用观察者模式的编程思想,只需要通过特定书写方式注册对应状态的事件处理函数,然后更新状态,调用注册过的处理函数即可。

这个特定方式就是then,done,fail,always…等方法,更新状态就是resolve、reject方法。

实现代码:

/**
* Promise类实现原理
* 构造函数传入一个function,有两个参数,resolve:成功回调; reject:失败回调
* state: 状态存储 [PENDING-进行中 RESOLVED-成功 REJECTED-失败]
* doneList: 成功处理函数列表
* failList: 失败处理函数列表
* done: 注册成功处理函数
* fail: 注册失败处理函数
* then: 同时注册成功和失败处理函数
* always: 一个处理函数注册到成功和失败
* resolve: 更新state为:RESOLVED,并且执行成功处理队列
* reject: 更新state为:REJECTED,并且执行失败处理队列
**/ class PromiseNew {
constructor(fn) {
this.state = 'PENDING';
this.doneList = [];
this.failList = [];
fn(this.resolve.bind(this), this.reject.bind(this));
} // 注册成功处理函数
done(handle) {
if (typeof handle === 'function') {
this.doneList.push(handle);
} else {
throw new Error('缺少回调函数');
}
return this;
} // 注册失败处理函数
fail(handle) {
if (typeof handle === 'function') {
this.failList.push(handle);
} else {
throw new Error('缺少回调函数');
}
return this;
} // 同时注册成功和失败处理函数
then(success, fail) {
this.done(success || function () { }).fail(fail || function () { });
return this;
} // 一个处理函数注册到成功和失败
always(handle) {
this.done(handle || function () { }).fail(handle || function () { });
return this;
} // 更新state为:RESOLVED,并且执行成功处理队列
resolve() {
this.state = 'RESOLVED';
let args = Array.prototype.slice.call(arguments);
setTimeout(function () {
this.doneList.forEach((item, key, arr) => {
item.apply(null, args);
arr.shift();
});
}.bind(this), );
} // 更新state为:REJECTED,并且执行失败处理队列
reject() {
this.state = 'REJECTED';
let args = Array.prototype.slice.call(arguments);
setTimeout(function () {
this.failList.forEach((item, key, arr) => {
item.apply(null, args);
arr.shift();
});
}.bind(this), );
}
} // 下面一波骚操作
new PromiseNew((resolve, reject) => {
resolve('hello world');
// reject('you are err');
}).done((res) => {
console.log(res);
}).fail((res) => {
console.log(res);
})

解释:当我们调用new Promise(fn)时,就会立即执行第一个参数fn。上面案例中,先将then(done,fail)对应的回调函数分别加入到doneList或者failList中,always中对应的参数同时加到doneList和failList中;

当异步代码执行完毕,就调用resolve方法,此时改变promise的状态为resolved,并执行doneList里面的回调函数。如果执行失败,则调用fail方法,此时改变promise的状态为rejected,并执行failList里面的回调函数。

模拟ES6中的Promise实现,让原理一目了然的更多相关文章

  1. 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise

    第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...

  2. [转]JS - Promise使用详解2(ES6中的Promise)

    原文地址:https://www.hangge.com/blog/cache/detail_1638.html 2015年6月, ES2015(即 ECMAScript 6.ES6) 正式发布.其中  ...

  3. es6中的promise对象

    Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) .Resol ...

  4. ES6中的Promise用法

    Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发. 当然,这并不代表迸发成了全栈.全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交 ...

  5. es6中的Promise学习

    关于Promise Promise实例一旦被创建就会被执行 Promise过程分为两个分支:pending=>resolved和pending=>rejected Promise状态改变后 ...

  6. ES6中的Promise使用方法与总结

    在javascript中,代码是单线程执行的,对于一些比较耗时的IO操作,都是通过异步回调函数来实现的. 但是这样会存在一个问题,当下一个的操作需要上一个操作的结果时,我们只能把代码嵌到上一个操作的回 ...

  7. ES6中的Promise和Generator详解

    目录 简介 Promise 什么是Promise Promise的特点 Promise的优点 Promise的缺点 Promise的用法 Promise的执行顺序 Promise.prototype. ...

  8. 深入解析ES6中的promise

    作者 | Jeskson来源 | 达达前端小酒馆 什么是Promise Promise对象是用于表示一个异步操作的最终状态(完成或失败)以及其返回的值. 什么是同步,异步 同步任务会阻塞程序的执行,如 ...

  9. ES6中的Promise详解

    Promise 在 JavaScript 中很早就有各种的开源实现,ES6 将其纳入了官方标准,提供了原生 api 支持,使用更加便捷. 定义 Promise 是一个对象,它用来标识 JavaScri ...

随机推荐

  1. [Swift]LeetCode319. 灯泡开关 | Bulb Switcher

    There are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off every ...

  2. 为什么大一先要学C语言(面向过程)再学C++或JAVA(面向对象)?

    面向对象和面向过程各有千秋 一.面向过程与面向对象对比  面向过程:强调的是每一个功能的步骤,有很多很多方法组成,这些方法相互调用,完成需求. 面向对象:强调的是对象,然后由对象去调用功能. 面向过程 ...

  3. 本地安装MySQL详细教程

    第1章   MySQL的安装与使用 1.1  MySQL安装与配置 1.1.1 MYSQL的安装 1.打开下载的mysql安装文件mysql-5.5.27-win32.zip,双击解压缩,运行“set ...

  4. Java代码复用的三种常用方式:继承、组合和代理

    复用代码是Java众多引人注目的功能之一.这句话很通顺,没什么问题,但问题在于很多人并不清楚“复用”是什么.就好像我说“沉默王二是一个不止会写代码的程序员”,唉,沉默王二是谁? 我们需要来给“复用”下 ...

  5. WeakHashMap

    WeakHashMap 今天在具体业务的时候看到HashMap和WeakHashMap的区别.因为PHP语言并没有这种概念.所以很好奇做了一下研究. WeakHashMap WeakHashMap所谓 ...

  6. 关于QT下资源使用和资源占用…

    原文地址:关于QT下资源使用和资源占用内存过多的问题作者:技术成就梦想     最近研究了一下如何从外部动态调用图片的问题,从而研究了图片资源的使用方法.网上最常见的帖子是这个,感觉总结的还不错. h ...

  7. JDK1.8源码(三)——java.util.HashMap

      什么是哈希表? 在讨论哈希表之前,我们先大概了解下其他数据结构在新增,查找等基础操作执行性能 数组:采用一段连续的存储单元来存储数据.对于指定下标的查找,时间复杂度为O(1):通过给定值进行查找, ...

  8. asp.net core系列 36 WebAPI 搭建详细示例

    一.概述 HTTP不仅仅用于提供网页.HTTP也是构建公开服务和数据的API强大平台.HTTP简单灵活且无处不在.几乎任何你能想到的平台都有一个HTTP库,因此HTTP服务可以覆盖广泛的客户端,包括浏 ...

  9. React Native (一) 入门实践

    上周末开始接触react native,版本为0.37,边学边看写了个demo,语法使用es6/7和jsx.准备分享一下这个过程.之前没有native开发和react的使用经验,不对之处烦请指出.笔者 ...

  10. 大战Java虚拟机【3】—— 类加载机制

    前言 当你的代码编译成class文件之后,那么虚拟机如何加载这些文件呢?我们需要知道虚拟机到底做了什么样的事情. 类的生命周期 加载--链接---初始化----使用---卸载 类加载过程 1.加载 读 ...