1、什么是Promise
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
这么说可能不够直观的理解,看下面的两个例子
// callback回调函数 function getCallback(n,callback) { setTimeout(() => { var num = 2*n console.log('num',num) callback(num) },2000) } getCallback(3,function callback(n) { console.log('n',n) }) // Promise函数的基础用法(等同于上面的回调函数) function runPro(n){ let p = new Promise((resolve,reject) => { setTimeout(() => { var num = 2*n console.log('num',num) resolve(num) },2000) }) return p } runPro(3).then((res) => { console.log('res',res) })
这么看是不是觉得Promise并没有什么特别的,而且还要费劲封装,有这功夫用回调函数就好了,那么在看下面的例子
// 三层callback回调函数(传说的回调地狱) function getCallback0(n,callback1) { setTimeout(() => { var num0 = 2*n console.log('num0',num0) callback1(num0,function callback2(params,callback3) { let num2 = params + 1 console.log('num2',num2) callback3(num2) }) },2000) } getCallback0(3,function callback1(n,callback2) { let num1 = n+1 console.log('num1',num1) callback2(num1,function callback3(params) { let num3 = params + 1 console.log('num3',num3) } ) }) // 三层Promise(等同于上面的回调函数) function runPro0(n){ let p = new Promise((resolve,reject) => { setTimeout(() => { var num0 = n*2 console.log('num0',num0) resolve(num0) },2000) }) return p } runPro0(3) .then((res) => { // console.log('res',res) let Pro1 = new Promise((resolve,reject) =>{ var num1 = res+1 console.log('num1',num1) resolve(num1) }) return Pro1 }) .then((res) =>{ // console.log('res',res) let Pro2 = new Promise((resolve,reject) =>{ var num2 = res+1 console.log('num2',num2) resolve(num2) }) return Pro2 }) .then((res) =>{ var num3 = res+1 console.log('num3',num3) // 如果需要可以继续回调 })
通过上面的对比可以很清除的看出,用Promise处理异步事件更加简洁直观
2、基础用法
const p = new Promise(function(resolve,reject){ if(success){ resolve('成功的结果') }else{ reject('失败的结果') } }) p.then(function (res) { // 接收resolve传来的数据,做些什么 },function (err) { // 接收reject传来的数据,做些什么 }) p.catch(function (err) { // 接收reject传来的数据或者捕捉到then()中的运行报错时,做些什么 })
p.finally(function(){
// 不管什么状态都执行
})
3、Promise的相关方法
Promise.prototype.then() Promise.prototype.catch() Promise.prototype.finally() Promise.resolve() Promise.reject() Promise.all() Promise.race()
由代码可以看出.then() .catch() .finally()都是定义在原型对象上的
4、then 的用法
由上面的基础用法代码可以看出.then()接收两个参数,第一个是resolved状态的回调函数,第二个是rejected状态的回调函数
5、catch的用法
.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。
6、finally的用法
.finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
7、all的用法
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调,all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。那么,三个异步操作返回的数据哪里去了呢?都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then。
(1)只有getNumber1、getNumber2、getNumber3的状态都变成fulfilled,Promise的状态才会变成fulfilled,此时getNumber1、getNumber2、getNumber3的返回值组成一个数组,传递给Promise的回调函数。
(2)只要getNumber1、getNumber2、getNumber3之中有一个被rejected,Promise的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给Promise的回调函数。
function getNumber1(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('1') resolve('随便什么数据1'); }, 1000); }); return p; } function getNumber2(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('2') reject('随便什么数据2'); }, 2000); }); return p; } function getNumber3(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('3') reject('随便什么数据3'); }, 3000); }); return p; } Promise.all([getNumber1(),getNumber2(),getNumber3()]) .then(function(res){ console.log('res',res) console.log('res',res[2].data) },function (err){ console.log('err',err) }) .catch(function(err2){ console.log('err2',err2) })
8、race的用法
Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
不过只要getNumber1、getNumber2、getNumber3之中有一个实例率先改变状态,Promise的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给Promise的回调函数。
注意:
1、Promise定义后就执行,所以通常用函数进行分装
2、Promise.all()中的参数是以一个数组传入的