什么是Promise呢?
- 定义:Promise是ES6异步编程的解决方案
那什么时候我们会处理异步事件呢?
- 一种很常见的场景就是网络请求了
- 我们封装一个网络请求的函数,因为不能立即拿到结果,而js代码又不能一直停在那里等
- 所以我们往往会传入另外一个函数,在数据请求成功后,将数据通过传入的函数调出去
- 如果一个简单的网络请求,可以使用这种方案,但是如果遇到异步的嵌套,就会出现回调地狱的问题,如下
$.ajax('url1', function(data1) {$(data1['url2'], function (data2) {$(data2['url3'], function (data3) {$(data3['url4'], function (data4) {console.log(data4);})})})})
如上代码难看且难以维护,我们可以使用Promise来解决这个问题
Promise的基本使用
- 我们使用setTimeout来模拟一个异步事件
- 一旦我们在Promise中调用了resolve()函数,就会来到.then()这个函数中
- 在这个then()中,对第一个setTimeout中的内容进行处理,处理完成后,如果还要进行下一个异步处理,就return一个新的Promise
- 这就成为了我们所说的链式编程 ```javascript setTimeout(() => { console.log(‘hello world’) }, 1000)
// 我们对如上异步操作进行封装,Promise中传入一个函数,其中两个参数resolve,reject也都是函数 new Promise((resole, reject) => { setTimeout(() => { resolve() }, 1000) }).then(() => { console.log(‘hello world’)
return new Promise ((resolve, reject) => { setTimeout(() => { resolve() }, 1000) }).then(() => { console.log(‘hello Vuejs’) }) })
- 什么情况下会用到Promise?>异步操作的时候,当我们要用到异步操作时,直接把异步操作那一坨代码往Promise里面一塞就行了,resolve()中的内容就会被传递到.then()中的data参数中,这样就可以在.then 中使用该数据了- 当然,如果网络请求失败了,就调用reject( )方法,括号中传入错误信息即可,此时不会进入.then( )方法,而是会进入.catch( )方法,将我们reject( ) 括号中的内容传入到 .catch ( ) 方法中进行相关的处理<a name="qwu3h"></a>## Promise 的三种状态- 当我们使用Promise时,异步操作就会出现三种状态- pending: 等待状态,比如正在进行网络请求,或者定时器没有到时间- fulfill:完成状态,当我们主动调用了resolve时,就处于该状态,并且会回调.then( )- reject:拒绝状态,当我们主动调用了reject时,就处于该状态,并且会回调.catch( )<a name="hrUHr"></a>## Promise 的链式调用- 对请求回来的结果进行链式的处理```javascriptnew Promise((resolve, reject) => {setTimeout(() => {resolve('aaa')}, 1000)}).then(res => {console.log(res, '第一层代码')return new Promise(resolve => {resolve(res + '111')})}).then(res => {console.log(res, '第二层代码')return new Promise(resolve => {resolve(res + '222')})}).then(res => {console.log(res, '第三层代码')})
对如上代码进行简化
new Promise((resolve, reject) => {setTimeout(() => {resolve('aaa')}, 1000)}).then(res => {console.log(res, '第一层代码')return Promise.resolve(res + '111')}).then(res => {console.log(res, '第二层代码')return Promise.resolve(res + '222')}).then(res => {console.log(res, '第三层代码')})
甚至还可以再简化,不用写Promise.resolve
new Promise((resolve, reject) => {setTimeout(() => {resolve('aaa')}, 1000)}).then(res => {console.log(res, '第一层代码')return res + '111'}).then(res => {console.log(res, '第二层代码')return res + '222'}).then(res => {console.log(res, '第三层代码')})
如果链式调用时,中间的一部分出现了错误,我们可以再链式最后面加上.catch( )方法来处理错误,在出现错误的地方通过return Promise reject(‘error message’)的方法抛出错误,或者通过throw ‘error message’ 的方式抛出错误,在最后面的catch方法都可以拿到这个错误
Promise 的all方法
如果我们想要完成一个需求,而这个需求需要两个网络请求都完成才能完成,那么该如何实现呢?
Promise.all([new Promise((resolve, reject) => {$ajax({url: 'url1',success: function (data) {resolve(data1)}})}),new Promise((resolve, reject) => {$ajax({url: 'url2',success: function (data) {resolve(data2)}})})]).then(results => {console.log(results)})
这样处理它内部就会判断,两个Promise都成功后才会执行后面的.then( )方法,且这个results中放的就是[data1, data2]
