1. promise的用途
一个html文档,正常来讲是会从上到下从第一行代码执行到最后一行代码的,会依次执行,这就是 同步
但是同步可能会带来一个问题。比如遇到网络请求时,我们知道,网络请求肯定是有延迟的,程序执行到网络请求那一步时由于是同步的,网络请求没有完成的那一段时间,用户会无法操作,这就大大影响了用户的体验。
所以网络请求一般是 异步 的,就是网络请求时,程序去服务器进行网络请求,但程序还是会继续运行下去,当网络请求结束后,会将网络请求到的东西通过回调函数传回到程序里进行显示。
我们之前都是通过 AJAX 来实现异步操作的,但是在碰到多次请求的情况可能会碰到“回调地狱”的情况
(第一次请求到的数据中有一部分数据需要第二次请求得到,第二次请求到的数据中有一部分数据又需要第三次请求得到,第三次请求到的数据中有一部分数据又需要第四次请求得到。。。。)
这样的代码看着太懵了,各种嵌套,当我们相对代码做修改时都不知道从何下手,要是有一个方法能把第一次到第四次的操作一个个提出来,清晰的一步步展示出来就好了
嗯,这个时候,Promise 就出来了
Promise是异步操作的一种解决方案
2. Promise的基本用法
new Promise((resolve, reject) => {
setTimeout(() => {
//resolve('请求成功!')
reject('请求失败')
},1000)
}).then(data => {
console.log(data)
}).catch(err => {
console.log(err)
})
Promise是个对象,它会传入一个函数作为参数。这个函数会接收两个函数作为参数,分别是resolve、reject。
上面的setTimeout其实是模仿网络请求的异步操作。
网络请求成功,就会执行回调函数resolve,拿到数据,就是我们这里的(请求成功!),再就会执行then方法,在then中对拿到的数据进行操作(就是这里的打印)
网络请求失败,就会执行回调函数reject,拿到错误报告,就是我们这里的(请求失败!),再就会执行catch方法,在catch中对拿到的错误报告进行操作(就是这里的打印)
上面是将then和catch分开写的,还有另外一种写法,可以只写then,在then中传两个函数
new Promise((resolve, reject) => {
setTimeout(() => {
//resolve('请求成功!')
reject('请求失败')
},1000)
}).then(data => {
console.log(data)
},err => {
console.log(err)
})
3. Promise的优点
看下面的例子,虽然看着代码量反而增多了,但是思路明确了。以前的嵌套都被抽出来,呈链式写出来了,三次的调用和操作都很明了,便于以后的阅读与维护。
Promise对象里只写网络请求,数据处理全部放在then里面,错误反馈全放到catch里面
而且虽然看着多,但后面还有简便写法。
不过需要注意的是:第一次的then紧跟着写在Promise对象后,第二次、第三次的then一定要写在前一个then方法的后面,then不能嵌套!!!
new Promise((resolve, reject) => {
//第一次请求数据
setTimeout(() => {
resolve()
},1000)
})
.then(() => {
//第一次操作数据
console.log("111")
return new Promise((resolve, reject) => {
//第二次请求数据
setTimeout(() => {
resolve()
},1000)
})
})
.then(() => {
//第二次操作数据
console.log("222")
return new Promise((resolve, reject) => {
//第三次请求数据
setTimeout(() => {
resolve()
},1000)
})
})
.then(() => {
//第三次操作数据
console.log("333")
})
4. Promise的三种状态
5. Promise的第二种链式调用
现在有一个需求:
网络请求:传入aaa,打印aaa,再处理10行代码
对aaa拼接一个111,打印,再处理10行代码
对上面的结果再拼接一个222,打印,再处理10行代码
前面的链式调用是请求,处理;请求,处理;请求,处理
现在是请求,处理;再处理,其他代码;再再处理,其他代码
下面是第二种调用的简写,,,,
这里的res是一路传下来的数据,它在这里其实就做了三次处理,其他的都只是程序的其他代码而已
resolve('aaa')
return Promise.resolve(res + '111')
return Promise.resolve(res + '222')
其实上面的还能简便写法 return Promise.resolve(res + ‘111’)可以直接写成 return res + ‘111’
举一反三:当请求失败怎么办呢?那肯定是将resolve换成reject,then换为catch,简便写法return换成throw
6. Promise的all方法
有时我们会遇到同时发送多个请求,并对多个请求下来的数据同时进行处理的情形
这时就需要用到Promise的all方法了
Promise.all([
new Promise((resolve, reject) => {
//第一次网络请求
}),
new Promise((resolve, reject) => {
//第二次网络请求
})
]).then((results) => {
//对第一次网络请求获取的数据进行操作
console.log(results[0]);
//对第二次网络请求获取的数据进行操作
console.log(results[1]);
})
results是两次请求的数据总和,results[0]、results[1]分别是第一次第二次网络请求得到的数据