es6中的promise解读
什么是promise?
简单的说它是一个异步流程的控制手段。是一个代表了异步操作最终完成或者失败的对象。
promise的优点
- promise解决了回调地狱的问题
- promise可以支持多个并发的请求
- promise的错误传播机制可以统一的处理错误信息
回调地狱问题
在传统的ajax调用过程中,下面以jquery.ajax为例。如果需求中要多次进行ajax交互,并且上一次的返回结果还要被下一次的ajax使用,代码基本上会变成:
$.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
$.ajax({
type: "POST",
url: "some.php",
data: msg,
success: function(msg2){
...//多次调用
}
});
}
});
现在还只是两次调用关系,如果是多次调用将会引发下面的问题
- 多次调用不利于代码的管理于维护
- 发生错误时不能及时准备的定位错误位置
- 只要又一次不成功就不能进行下面的逻辑,不方便进行错误处理。
promise的链式调用就很好的解决了这个问题
Promise的三种状态
- Pending Promise对象实例创建时候的初始状态
- resolve 可以理解为成功的状态
- Reject 可以理解为失败的状态
promise 中的状态只能是从等待状态转换到成功状态或者失败状态,且状态转变之后不可逆。

一个简单的promise
let p = new Promise((resolve, reject) => {
console.log(1)
});
console.log(2)
//1 2
promise里面只接受一个参数,叫做执行器函数,这个函数会同步执行。也就是说上面代码中的箭头函数被同步执行,得到的结果也就是1和2
promise中的then
每一个promise的实例上都有一个then方法,这个方法上有两个参数,一个是成功的回调,一个是失败的回调。而取决于成功或者失败的是promise的执行器函数中执行的是成功还是失败。
let p = new Promise((resolve, reject) => {
console.log(1);
resolve();//调用resolve会走到then的成功回调
//reject();//调用resolve会走到then的失败回调
});
p.then(
() => {
console.log('成功')
}
, () => {
console.log('失败')
})
//1 成功
如果既不调用resolve也不调用reject,promise则一直处于等待状态,也就不会走到then方法。
let p = new Promise((resolve, reject) => {
console.log(1);
});
p.then(
() => {
console.log('成功')
}
, () => {
console.log('失败')
})
//1
如果你既调用resolve也调用reject,那么谁在前面执行就走谁的对应回调函数
let p = new Promise((resolve, reject) => {
console.log(1);
resolve()//先调用成功
reject()
});
p.then(
() => {
console.log('成功')
}
, () => {
console.log('失败')
})
//1 成功
let p = new Promise((resolve, reject) => {
console.log(1);
reject()//先调用失败
resolve()
});
p.then(
() => {
console.log('成功')
}
, () => {
console.log('失败')
})
//1 失败
如果代码出错则会直接走reject的回调
let p = new Promise((resolve, reject) => {
console.log(1);
throw new Error('出错了~')
});
p.then(
() => {
console.log('成功')
}
, () => {
console.log('失败')
})
//1 失败
一个promise的实例可以then多次
let p = new Promise((resolve, reject) => {
resolve('成功了');
});
p.then((data) => {
console.log(data)//成功了
});
p.then((data) => {
console.log(data)//成功了
})
利用promise解决回调地狱
能够规避异步操作中回调地狱的问题,其本质取决于promise的链式调用。
假设需求如下,a.txt文件的内容为b.txt,b.txt文件的内容是一段描述文字,现在要求用a.txt的得到最终的描述文字,代码如下:
let fs = require('fs');
//首先将异步方法封装在一个promise中,异步结果成功调用resolve方法,失败调用reject方法。
function read(url) {
return new Promise((resolve, reject) => {
fs.readFile(url, 'utf8', function (err, data) {
if (err) reject();
resolve(data);
})
})
}
//因为read方法返回的是一个promise,所以可以使用promise的then方法
read('a.txt').then((data) => {
//第一次异步成功后拿到结果继续返回一个promise可以实现链式调用。
console.log(data);//b.txt
return read(data);
}, (err) => { }).then((data) => {
//最后两次的结果分别对应两次异步的返回内容
console.log(data)//描述文字
}, (err) => { })
总结:如果一个promise的then方法中还返回另一个promise,那么这个promise的成功状态会走到外层promise的下一次then方法的成功,如果失败,返回外层promise下一次then的失败。
promise的链式调用
- 如果then中返回的是一个普通值,就会走到下一次then的成功回调。
read().then((data) => {
return 111
}, (err) => { }).then((data) => {
console.log(data)//111
}, (err) => { })
- 如果then中返回的是一个错误,就会走到下一次then的失败回调。
read().then((data) => {
throw new Error('出错了~')
}, (err) => { }).then((data) => {
console.log(data)
}, (err) => {
console.log(err)//出错了~
})
- 如果then中什么也不返回,就会走到下一次then的成功回调,得到的值为undefined。
read().then((data) => {
cons.log(111)
}, (err) => { }).then((data) => {
console.log(data)//undefined
}, (err) => {
})
- 如果想统一处理错误内容,可以使用catch。
read().then((data) => {
throw new Error('出错了~')
}, (err) => { }).then((data) => {}, (err) => {}).catch((err)=>{
//错误处理
})
- 统一处理错误后,还可以使用then。
read().then((data) => {
throw new Error('出错了~')
}, (err) => { }).then((data) => {}, (err) => {}).catch((err)=>{
//错误处理
}).then((data) => {}, (err) => {})
Promise.all()
all方法可以处理多个请求并发的问题。参数是一个数组。all方法调用后会返回一个新的promise。
let fs = require('fs');
function read(url) {
return new Promise((resolve, reject) => {
fs.readFile(url, 'utf8', function (err, data) {
if (err) reject();
resolve(data);
})
})
}
Promise.all([read('1.txt'), read('2.txt')]).then((data) => {
console.log(data)//[ '文本1内容', '文本2内容' ]
}, (err) => {
console.log(err);
})
在all方法中一个失败了就全部失败,所以都成功了才会走成功回调。
Promise.all([read('1.txt'), read('3.txt')]).then((data) => {
console.log(data)
}, (err) => {
console.log('失败了');//失败了
})
Promise.race()
多个请求中,谁的返回数据最快,结果就是谁
Promise.race([read('1.txt'), read('2.txt')]).then((data) => {
console.log(data)////文本2内容
}, (err) => {
console.log('失败了');//失败了
})
Promise.resolve()
返回一个成功的Promise
Promise.resolve('123').then((data) => {
console.log(data)//123
})
Promise.reject()
返回一个失败的Promise
Promise.resolve('123').then((data) => {
console.log('err', data)//err 123
})
如果你想手写一个promise,请戳下面的链接:
手写promise
es6中的promise解读的更多相关文章
- 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise
第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...
- ES6中的Promise和Generator详解
目录 简介 Promise 什么是Promise Promise的特点 Promise的优点 Promise的缺点 Promise的用法 Promise的执行顺序 Promise.prototype. ...
- es6中的promise对象
Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) .Resol ...
- ES6中的Promise用法
Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发. 当然,这并不代表迸发成了全栈.全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交 ...
- es6中的Promise学习
关于Promise Promise实例一旦被创建就会被执行 Promise过程分为两个分支:pending=>resolved和pending=>rejected Promise状态改变后 ...
- ES6中的Promise使用方法与总结
在javascript中,代码是单线程执行的,对于一些比较耗时的IO操作,都是通过异步回调函数来实现的. 但是这样会存在一个问题,当下一个的操作需要上一个操作的结果时,我们只能把代码嵌到上一个操作的回 ...
- [转]JS - Promise使用详解2(ES6中的Promise)
原文地址:https://www.hangge.com/blog/cache/detail_1638.html 2015年6月, ES2015(即 ECMAScript 6.ES6) 正式发布.其中 ...
- 理解ES6中的Promise
一.Promise的作用 在ajax请求数据的过程中,我们可以异步拿到我们想要的数据,然后在回调中做相应的数据处理. 这样做看上去并没有什么麻烦,但是如果这个时候,我们还需要做另外一个ajax请求,这 ...
- ES6中的Promise详解
Promise 在 JavaScript 中很早就有各种的开源实现,ES6 将其纳入了官方标准,提供了原生 api 支持,使用更加便捷. 定义 Promise 是一个对象,它用来标识 JavaScri ...
随机推荐
- maven项目打包分析及打包后war包缺少配置文件报错的原因分析,使用progard混淆时配置分析
1.maven打包: 一直以来我都没太注意过在myeclipse下使用run as来clean居然对项目的target目录没有进行操作,要让操作有效,需要进入到maven build...选项下,进行 ...
- 禁止tableview 像上滑动
tableView有一个bounces属性.默认YES,所以tableView上下用力拉都会有弹性滑动,如下设置可以禁止,但是这样的话上下弹性都没了 而经常的需求是上方不要弹性,下方要弹性,可以用监听 ...
- Luogu P3223 [HNOI2012]排队 组合
本来做了一道 P4901 排队 后来发现自己做错题了...到也都是数学qwq 这题最恶心的就是两只(雾)老师. 那我们分类讨论: 1.两个老师之间是男生: $ A(n,n)*A(n+1,2)*A(n ...
- (1009) HDU 6446 Tree and Permutation(规律+树上各个点的距离和)
题意: 给一棵N个点的树,对应于一个长为N的全排列,对于排列的每个相邻数字a和b,他们的贡献是对应树上顶点a和b的路径长,求所有排列的贡献和. 分析: 经过简单的分析可以得知,全部的贡献其实相当与(这 ...
- Docker从入门到实战(一)
Docker从入门到实战(一) 一:容器技术与Docker概念 1 什么是容器 容器技术并不是一个全新的概念,它又称为容器虚拟化.虚拟化技术目前主要有硬件虚拟化.半虚拟化.操作系统虚拟化等.1.1关于 ...
- object.wait为什么要和synchronized一块使用
Object.wait 中JDK提供的doc文档 Causes the current thread to wait until another thread invokes the notify() ...
- @Import @bean,@Conditional @ConfigurationProperties @EnableConfigurationProperties 注解使用
一分钟学会spring注解之@Import注解http://blog.51cto.com/4247649/2118354 @Autowired与@Resource 注解的使用 https://www. ...
- 07.Spring Bean 加载 - BeanDefinitionReader
基本概念 BeanDefinitionReader ,该接口的作用就是加载 Bean. 在 Spring 中,Bean 一般来说都在配置文件中定义.而在配置的路径由在 web.xml 中定义.所以加载 ...
- 物理机和虚拟机互相可以ping通,还是无法连接
关闭防火墙服务 CentOS # systemctl stop firewalld.service Debian # iptables -F Ubuntu # ufw disable 安装SSH服务 ...
- SpringBoot | 第八章:统一异常、数据校验处理
前言 在web应用中,请求处理时,出现异常是非常常见的.所以当应用出现各类异常时,进行异常的捕获或者二次处理(比如sql异常正常是不能外抛)是非常必要的,比如在开发对外api服务时,约定了响应的参数格 ...