ES6为什么推出Promise
Promise 是ES6新增的引用类型,让我们的异步逻辑代码更加优雅。
异步就相当于你会了影分身,本来你只能同一时间做一个事情,但是当你有了分身之后,你可以和他同一时间做不同的事情。

所以,异步增加了我们事情完成的效率,这也就是我们常说的避免进程等待一个长时间的线程操作,同时执行,减少耗时,增加性能。
异步是JavaScript的基础,之前的异步实现并不理想。以前,想要表明一个异步操作的完成,只能通过回调函数来完成,当异步当中还有异步,如此反复多次,就是常说的回调噩梦
但是当有了Promise就不一样了,我们不需要回调嵌套,逻辑清晰、代码优雅的完成了异步操作。
我们来对比下吧。以嵌套三次为例。不需要看懂代码,只需要对比下哪种更优雅。
以前异步嵌套
1//定义一个异步函数 2function double(value, success, failure) { 3 setTimeout(() => { 4 try { 5 if(typeof value === 'number'){ 6 success(2 * value); 7 }else{ 8 throw '参数必须是数字'; 9 } 10 } catch (error) { 11 failure(error); 12 } 13 }, 100); 14} 15 16//注意这里。这是成功回调。z用到了y,y用到了x,所以需要嵌套3层 17const successCallback = (x)=>{ 18 double(x,(y)=>{ 19 double(y,(z)=>{ 20 console.log('success:',z); 21 }) 22 }) 23} 24//失败回调 25const failureCallback = (e)=>{ 26 console.log('failure',e); 27} 28double(3, successCallback, failureCallback);
有了Promise的异步多层回调
1//定义一个工厂方法 2function doublePromise(value){ 3 let p1 = new Promise((resolve,reject)=>{ 4 if(typeof value === 'number'){ 5 setTimeout(()=>{ 6 try { 7 resolve(2*value); 8 console.log('success:',2*value); 9 } catch (error) { 10 reject(error); 11 console.log('failure',error); 12 } 13 } , 100); 14 }else{ 15 throw '参数必须是数字'; 16 } 17 }) 18 return p1 19} 20 21//promise将异步串行化,避免了回调噩梦 22doublePromise(3).then((value1)=>{ 23 console.log(typeof value1) 24 return doublePromise(value1) 25}).then((value2)=>{ 26 console.log(value2) 27 return doublePromise(value2) 28})
目前还是三层的,越多的话就越发现Promise的优雅与简洁。
Promise(期约)
基本表现形式
1new Promise((resolve,reject)=>{ 2 3})
Promise的三种状态:
-
待定(pending)
1new Promise((resolve,reject)=>{ 2 3})//Promise {<pending>}
未定义其他状态,且未改变其状态时,期约为pending状态
-
兑现(fulfilled,也可称作解决,resolved)
1new Promise((resolve,reject)=>{ 2 resolve() 3})//Promise {<fulfilled>: undefined}
-
拒绝(rejected)
1new Promise((resolve,reject)=>{ 2 reject() 3})//Promise {<rejected>: undefined}
-
状态变更规则
注意!Promise从待定状态改变为兑现或拒绝,只能改变一次。
1let p = new Promise((resolve,reject)=>{ 2 resolve(); 3 reject(); 4}); 5console.log('期约状态:',p) 6//或许你以为是期约状态:Promise<rejected>,实际上是期约状态:Promise<resolved>
Promise初始状态并非一定是pedding(待定)状态:
1let p1 = new Promise((resove,reject) => resove()); 2let p2 = Promise.resove(); 3//p1 和 p2两个都是解决期约
解决期约Promise.resolve()
解决期约(Promise.resolve())可包装任何非期约值,就算是错误对象,并只接受一个参数值!若参数为期约,则返回参数参数期约,可将外层期约看作个空包装。可以说Promise.resolve()是一个幂等方法。此幂等性还会保留期约传入的状态。类似我们学过的函数方程:f(f(x)) = f(x)
代码:
1let p3 = Promise.resolve(1); 2let p4 = Promise.resolve(p3); 3console.log(p3===p4); //true 4
拒绝期约(Promise.reject())
拒绝期约(Promise.reject()),会实例化一个拒绝期约,并抛出一个异步错误。该错误不能通过try/catch捕获,只能通过拒绝处理程序捕获。参数如果传入一个期约,则这个期约将成为拒绝的理由。
代码:
1let p = Promise.reject(Promise.resolve()); 2console.log('p:', p); 3// p: Promise { <state>: "rejected", <reason>: Promise { "fulfilled" } }
Promise的实例方法
三个方法,一个处理方法,一个拒绝处理方法。一个无论拒绝还是处理都会执行的方法。
你跟我表白,我得告诉你我接受不接受吧,虽然很多渣男渣女吊着你,但是程序不会吊着你,除非没网,那个时候就是渣程序。还有无论接受不接受,不影响我找你借钱吧

处理方法then()
可以传两个参数,Promise.prototype.then(onResoved,onRejected)。返回值为一个新Promise对象
1let p = new Promise((resolve,reject)=>{ 2 resolve('我接受你啦') 3}); 4p.then(()=>{ 5 console.log('我同意我同意,你好帅哇,想给你大马猴') 6})
拒绝处理方法catch()
类似一个语法糖,等同于Promise.prototype.then(null,onRejected)。返回值为一个新Promise对象
1let p = new Promise((resolve,reject)=>{ 2 reject('不行!') 3}); 4p.catch(()=>{ 5 console.log('你太丑了') 6})
兑现或拒绝都会执行的方法finally()
返回值为一个新Promise对象
1let p = new Promise((resolve,reject)=>{ 2 reject('不行!') 3}); 4p.finally(()=>{ 5 console.log('不过你能借我点钱嘛?') 6})
入门就到这里,下一篇深入。
