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

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

不难想象,如果依次有很多个动画,就会出现多重嵌套。代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理。
因为多个异步操作形成了强耦合,只要有一个操作需要修改,它的上层回调函数和下层回调函数,可能都要跟着修改。这种情况就称为回调函数地狱“(callback hell)。
Promise 对象就是为了解决这个问题而提出的。它不是新的语法功能,而是一种新的写法,允许将回调函数的嵌套,改成链式调用。
浏览器实现方式:可以在支持Promise的版本上运行

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

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), 200);
} // 更新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), 200);
}
} // 下面一波骚操作
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里面的回调函数。
原文:https://www.cnblogs.com/minigrasshopper/p/9141307.html
promise原理的更多相关文章
- Promise原理 && 简单实现
Promise原理 参考https://github.com/chunpu/promise/blob/master/promise.js 个人认为原博的实现有点问题 在next函数的实现上, 会导致无 ...
- Promise 原理
异步:可同时好几件事,互不影响: 同步:按循序一件一件.... 异步好多缺点:.... promise就是解决异步计算的这些缺点的,主要用于: 1.异步计算: 2.可以将异步操作队列化 按期望的顺序 ...
- 这一次,彻底弄懂 Promise 原理
作者声明 本人将迁移至个人公众号「前端Q」及「掘金」平台写文章.博客园的文章将不再及时更新发布.欢迎大家关注公众号「前端Q」及我的掘金主页:https://juejin.im/user/5874526 ...
- Promise原理—一步一步实现一个Promise
promise特点 一个promise的当前状态只能是pending.fulfilled和rejected三种之一.状态改变只能是pending到fulfilled或者pending到rejected ...
- 30分钟,让你彻底明白Promise原理
前言 前一阵子记录了promise的一些常规用法,这篇文章再深入一个层次,来分析分析promise的这种规则机制是如何实现的.ps:本文适合已经对promise的用法有所了解的人阅读,如果对其用法还不 ...
- Promise原理剖析
传统的异步回调编程最大的缺陷是:回调地狱,由于业务逻辑非常复杂,代码串行请求好几层:并行请求以前也要通过引用step.async库实现.现在ES6推出了Promise,通过Promise的链式调用可以 ...
- ES6之promise原理
我在这里介绍了promise的原理: https://juejin.im/post/5cc54877f265da03b8585902 我在这里 仅仅张贴 我自己实现的简易promise——DiProm ...
- Promise原理实现
首先先看一下 promise 的调用方式: // 实例化 Promise: new MyPromise((resolve, reject) => { setTimeout(() => { ...
- 10分钟,让你彻底明白Promise原理
什么是Promise?本代码用定外卖来举例子,让你明白. // 定外卖就是一个Promise,Promist的意思就是承诺// 我们定完外卖,饭不会立即到我们手中// 这时候我们和商家就要达成一个承诺 ...
随机推荐
- Scrapy爬取Ajax(异步加载)网页实例——简书付费连载
这两天学习了Scrapy爬虫框架的基本使用,练习的例子爬取的都是传统的直接加载完网页的内容,就想试试爬取用Ajax技术加载的网页. 这里以简书里的优选连载网页为例分享一下我的爬取过程. 网址为: ht ...
- Netty源码—三、select
NioEventLoop功能 前面channel已经准备好了,可以接收来自客户端的请求了,NioEventLoop作为一个线程池,只有一个线程,但是有一个queue存储了待执行的task,由于只有一个 ...
- api接口参数问题
对于取数据,我们使用最多的应该就是get请求了吧.下面通过几个示例看看我们的get请求参数传递. 回到顶部 1.基础类型参数 [HttpGet] public string GetAllChargin ...
- headfirst设计模式(9)—模板方法模式
前言 这一章的模板方法模式,个人感觉它是一个简单,并且实用的设计模式,先说说它的定义: 模板方法模式定义了一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式.让子类别在不改变算法架构的情况下, ...
- salesforce初探
Salesforce的商业模式? 从做CRM SAAS起家,可以理解为在线CRM,不需要硬件和服务器,输入用户名和密码就能登陆使用.2007年推出PaaS平台Force.com,可以说,它依托CR ...
- [题解] 2038: [2009国家集训队]小Z的袜子(hose)
莫队,卡常数 题目地址 思路 设\(\text{Vis[i]}\)为元素\(\text{i}\)在区间\(\text{[L,R]}\)的出现次数 考虑区间\(\text{[L,R]}\)和元素\(\t ...
- NodePort,LoadBalancer还是Ingress?我该如何选择 - kubernetes
原文:http://mp.weixin.qq.com/s/dHaiX3H421jBhnzgCCsktg 当我们使用k8s集群部署好应用的Service时,默认的Service类型是ClusterIP, ...
- 将博客搬至CSDN https://blog.csdn.net/Fredric_2014
将博客搬至CSDN https://blog.csdn.net/Fredric_2014
- JDK中的Atomic包中的类及使用
引言 Java从JDK1.5开始提供了java.util.concurrent.atomic包,方便程序员在多线程环境下,无锁的进行原子操作.原子变量的底层使用了处理器提供的原子指令,但是不同的CPU ...
- Servlet不再是烦恼
Servlet 一.什么是Servlet? Servlet是在服务器上运行的小程序,也就是一个Java类,但比较特殊,不需要new,自动就可以运行.也有创建.垃圾回收和销毁过程.Servlet是Jav ...