Promise是一个对象,同时也是一个构造函数,为了对Promise有一个直观的认识,首先咱们把Promise直接在控制台打印出来:
经过这张图片咱们能够很清除地看到,Promise本身身上有all,race,resolve,reject这些咱们熟悉的方法,而在原型之上,则有then,catch,finally这些一样很熟悉的方法。javascript
既然Promise是一个构造函数,那咱们就new一个实例出来吧:java
var p = new Promise(function(resolve,reject){ setTimeout(() =>{ if(1){ //假设操做成功 console.log("执行成功") resolve("执行成功以后的数据") }else{ console.log("执行失败") reject("执行失败以后的数据") } }, 1000) })
Promise接收一个参数,是一个函数,该函数有两个参数:resolve和reject,也是两个函数,这两个函数是javascript引擎给咱们提供的,不用咱们本身去部署。
Promise有三种状态:pending/fulfilled/rejected 。pending就是未决,fulfilled能够理解为成功,rejected能够理解为失败。数组
resolve函数的做用是将Promise的状态置为fullfiled,当状态变成fullfiled时,then方法的第一个回调会执行,reject函数是将Promise的状态置为rejected,当状态变成rejected时,then方法的第二个回调或者catch方法里的回调会执行异步
而且Promise有如下特色:
1 .对象的状态不受外界影响,只有内部异步操做的结果能够修改他的状态,任何其余操做都没法修改他的状态。
2 .一旦状态发生改变,就不会再变,任什么时候候均可以获得这个结果。若是改变已经发生了,只要添加回调函数,任什么时候候均可以获得返回值。函数
运行以上代码,咱们在控制台能够看到打印出了执行成功:
注意,这里咱们只是new了一个Promise对象,并无去调用它,里面代码就已经执行了,因此咱们通常都是把Promise放到一个函数里面,在须要的时候调用,为了方便探讨,咱们对函数作以下封装:spa
function createPro(num,time){ return new Promise(function(resolve,reject){ setTimeout(() =>{ if(num > 5){ console.log("执行成功") resolve("执行成功以后的数据") }else{ console.log("执行失败") reject("执行失败以后的数据") } }, time) }) }
咱们封装了一个函数,返回一个Promise对象,咱们给该函数传递两个参数,num和time,num用来控制异步操做的结果,num大于5理解为执行成功,time用来控制延迟时间。
刚才咱们看到函数已经执行成功,可是resolve和reject传递的参数去哪里了?还记得刚才咱们说过当Promise状态改变时会执行then或者catch方法里的回调吧,没错,在回调函数里面就能够取到传递的数据。code
then中有2个参数,第一个参数是状态变为成功后应该执行的回调函数,第二个参数是状态变为失败后应该执行的回调函数。对象
createPro(10,1000).then((data)=>{ console.log("num为10时then方法的第一个参数收到的:"+data) },(err)=>{ console.log("num为10时then方法的第二个参数收到的:"+err) }) createPro(1,1000).then((data)=>{ console.log("num为1时then方法的第一个参数收到的:"+data) },(err)=>{ console.log("num为1时then方法的第二个参数收到的:"+err) })
执行以上函数,咱们观察控制台的打印状况:blog
因为第一次调用createPro时,咱们给num传的值为10,比5要大,因此在函数内部执行了resolve方法,Promise的状态变成了fullfiled,then方法的第一个回调被执行,而且接收到了resolve方法传递来的数据,而在第二次调用createPro时,咱们给num传的值为1,比5要小,因此在函数内部调用了reject方法,Promise的状态变成了rejected,then方法的第二个回调被执行,而且收到了reject传递的数据。
固然then方法也能够只接收一个回调,即异步操做成功时执行的回调。
catch方法是用来接收异步操做失败的结果,效果和then方法的第二个参数同样:接口
createPro(1,1000).then((data)=>{ console.log("then方法的第一个参数收到的:",data) }).catch((err)=>{ console.log("catch方法里收到的:",err) })
咱们在控制台能够看到打印了:
若是咱们想要无论成功仍是失败,都要执行一些操做能够用Promise.finally(),可是该方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态究竟是fulfilled仍是rejected。这代表,finally方法里面的操做,是与状态无关的,不依赖于 Promise 的执行结果。
Promise的then方法以后会继续返回一个Promise对象,能够继续调用then方法,而接收的参数值就是上一个then方法return的结果:
createPro(10,1000).then((data)=>{ console.log("then方法的第一个参数收到的:"+data) return 100 }).then(data=>{ console.log("第二个then方法接收到的的参数",data) })
咱们能够看到在第二个then中接收到了咱们在第一个then方法中返回的数字100.固然咱们也能够返回一个Promise对象
createPro(10,1000).then((data)=>{ console.log("第一个then:",data) return createPro(10,1000) }).then(data=>{ console.log("第二个then:",data) return createPro(2,1000) }).then(data=>{ console.log("第三个then:",data) return createPro(10,1000) }).catch(err=>{ console.log("公共的catch方法:",err) })
运行结果以下:
咱们能够看到函数依次执行,因此Promise能够解决所谓“地狱回调”的问题,而且若是中途有异步操做执行失败,都会执行catch里面的回调。
Promise的all方法提供了并行执行异步操做的能力,而且在全部异步操做执行完后才执行回调。Promise.all接收一个数组参数,里面的异步操做的并行执行的,等到它们都执行完后才会进到then里面。那么,异步操做返回的数据哪里去了呢?都在then里面呢,all会把全部异步操做的结果放进一个数组中传给then。
咱们对createPro函数设置不一样的延迟时间:
Promise.all([createPro(10,1000),createPro(10,2000),createPro(10,3000)]).then(data=>{ console.log(data) })
执行以上代码,咱们能够看到控制台每隔一秒打印出了一次“执行成功”,而且在最后打印出了传递的数据,是一个数组:
Promise.all有一个常常用到的场景就是,在一个页面有多个请求接口,当全部接口都请求到数据以后,关闭loading遮罩层,这时候咱们就能够用到Promise.all方法。
理解了Promise.all再来看Promise.race就好理解多了,all方法的效果其实是「谁跑的慢,以谁为准执行回调」,那么相对的就有另外一个方法「谁跑的快,以谁为准执行回调」,这就是Promise.race:
Promise.race([createPro(10,1000),createPro(10,2000),createPro(10,3000)]).then(data=>{ console.log(data) })
运行结果以下:
咱们在控制台能够看到,一秒以后打印出了“执行成功”,而且拿到了resolve传递的数据,可是另外两个函数并无中止运行,因此咱们看到每间隔一秒又打印出了“执行成功”。
关于Promise经常使用的方法先写这些了,另外还有Promise.resolve和Promise.reject等方法有时间再研究,因为做者水平有限,文章不免有错误之处,还请大神斧正。