es6中的promise解读
栏目: JavaScript · 发布时间: 5年前
内容简介:简单的说它是一个异步流程的控制手段。是一个代表了异步操作最终完成或者失败的对象。在传统的ajax调用过程中,下面以jquery.ajax为例。如果需求中要多次进行ajax交互,并且上一次的返回结果还要被下一次的ajax使用,代码基本上会变成:现在还只是两次调用关系,如果是多次调用将会引发下面的问题
简单的说它是一个异步流程的控制手段。是一个代表了异步操作最终完成或者失败的对象。
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 }) 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Phoenix解读 | Phoenix源码解读之索引
- Phoenix解读 | Phoenix源码解读之SQL
- Flink解读 | 解读Flink的声明式资源管理与自动扩缩容设计
- 解读阿里巴巴 Java 代码规范,第 2 部分: 从代码处理等方面解读阿里巴巴 Java 代码规范
- websocket 协议解读
- AQS源码详细解读
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
UNIX编程环境
Brian W.Kernighan、Rob Pike / 陈向群/等 / 机械工业出版社 / 1999-10-1 / 24.00
本书对UNIX操作系统的编程环境做了详细而深入的讨论,内容包括UNIX的文件系统、Shell、过滤程序、I/O编程、系统调用等,并对UNIX中的程序开发方法做了有针对性的指导。本书内容深入浅出,实例丰富,无论是UNIX系统的初学者还是专业人员都可从本书受益。本书亦可作为大学生、研究生学习UNIX的教材。一起来看看 《UNIX编程环境》 这本书的介绍吧!