31Promise
异步编程的一种解决方案。
1.何为异步
网络请求中,对端服务器处理需要时间,信息传递过程需要时间,不像我们本地调用一个js加法函数一样,直接获得1+1=2
的结果。这里网络请求不是同步的有时延,不能立即得到结果。
2.如何处理异步事件
对于网络请求,一般会使用回调函数在服务端传给我数据成功后,调用回调函数。例如ajax调用。
$.ajax({
success:function(){
...
}
})
如果碰到嵌套网络请求,例如第一次网络请求成功后回调函数再次发送网络请求,这种代码就会让人很难受。
$.ajax({
success:function(){
$.ajax({
...
})
}
})
如果还需要再次网络请求,那么又要嵌套一层,这样的代码层次不分明很难读,也容易出问题。
2.基本使用
解决异步请求冗余这样的问题,promise就是用于封装异步请求的。
new Promise((resolve, reject) => {})
resolve和reject本身也是函数。
因为没有真正的网络请求,这里使用setTimeout模拟异步请求
这种方式一层套一层很乱
//1.使用setTimeout模拟嵌套的三次网络请求
setTimeout(() => {//第一次请求
console.log("hello world")//第一次处理代码
setTimeout(() => {//第二次请求
console.log("hello vuejs")//第二次处理代码
setTimeout(() => {//第三次请求
console.log("hello java")//第三次处理代码
}, 1000)
}, 1000)
}, 1000)
使用Promise处理异步请求,调用resolve()可跳转到then方法处理代码,而then中回调中又存在一个promise对象,这就是链式调用。
//参数 -> 函数
// resolve和reject本身也是函数
//then()的参数也是一个函数
new Promise((resolve, reject) => {
setTimeout(() => {//第一次网络请求
resolve()
}, 1000)
}).then(() => {
console.log("hello world")//第一次处理代码
return new Promise((resolve, reject) => {
setTimeout(() => {//第二次网络请求
resolve()
}, 1000).then(() => {
console.log("hello vuejs")//第二次处理代码
return new Promise((resolve, reject) => {
setTimeout(() => {//第三次网络请求
resolve()
}, 1000)
}).then(() => {
console.log("hello java")//第三次处理代码
})
})
})
})
setTimeout()模拟的是网络请求,而then()执行的是网络请求后的代码,这就将网络请求和请求得到响应后的操作分离了,每个地方干自己的事情。在resolve中传参了,那么在then()方法中的参数就有这个参数,例如data。
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000).then(success => {
console.log(success)
})
})
网络请求中也有错误的情况,此时调用reject(),此时reject(error)
,catch()
方法捕获到reject()
中的error。
new Promise((resolve, reject) => {
setTimeout(() => {
reject('error message')
}, 1000).catch(error => {
console.log(error)
})
})
总的使用:
new Promise((resolve, reject) => {
setTimeout(() => {
// 成功的时候调用resolve()
// resolve('hello world')
// 失败的时候调用reject()
reject('error message')
}, 1000).then(success => {
console.log(success)
}).catch(error => {
console.log(error)
})
})
ajax例子:
new Promise((resolve, reject) => {
$.ajax({
success:function(){
// 成功的时候调用resolve()
// resolve('hello world')
// 失败的时候调用reject()
reject('error message')
}
}).then(success => {
console.log(success)
}).catch(error => {
console.log(error)
})
})
3.Promise三种状态
- pending:等待状态,比如正在进行的网络请求还未响应,或者定时器还没有到时间
- fulfill:满足状态,当我们主动回调了resolve函数,就处于满足状态,并会回调then()
- reject:拒绝状态,当我们主动回调reject函数,就处于该状态,并且会回调catch()
3.案例
成功调用promise三种写法
1
// 正确情况1
new 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+'2222')
})
}).then(res=>{
console.log(res,'第三层处理');
})
2
// 正确情况2
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,"第三层处理代码");
}).catch(err=>{
console.log(err);
})
3
// 正确情况3
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(err=>{
console.log(err);
})
错误情况,可以两种错误异常写法
第一种
// return Promise.reject('error message')
第二种
throw 'error message'
当执行到异常时下方就不再执行了。
// 错误情况
// 当出现错误时下方就不再执行了
new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('aaa')
}, 1000);
}).then(res =>{
console.log(res,'第一层处理代码');
// return Promise.reject('error message')
throw 'error message'
reject('error')
}).then(res=>{
console.log(res,"第二层处理代码");
return res+'222'
}).then(res=>{
console.log(res,"第三层处理代码");
}).catch(err=>{
console.log(err);
})