Promise
Promise是为了解决异步编程导致回调函数嵌套太深,陷入回调地狱
传统异步编程
$.ajax('url',function(data1){
$.ajax(data1['url2'],function(data2){
$.ajax(data2['url3'],function(data3){
$.ajax(data3['url4'],function(data4){
console.log(data4)
})
})
})
})
上面的代码有什么问题呢?
- 正常情况下不会有什么问题,可以正常运行并且获取到我们想要的结果.
- 但是,这样的代码难看且不容易维护
- 我们期望是一种更加优雅的方式来进行这种异步操作.
就是使用Promise
Promise的基本使用
正常使用异步方法
setTimeout(() => {
console.log("Hello World")
},1000)
使用Promise
// 简单使用Promise
// 参数 -> 函数(resolve, reject)
// resolve, reject本身它们又是函数
new Promise((resolve, reject) => {
setTimeout(()=>{
//成功时调用
resolve('Hello World')
//失败时调用
reject('error')
})
}).then(data=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
// 执行resolve时,会调用then方法,执行reject时会调用catch方法
// 在执行异步操作时可能成功或者失败.
// 成功时执行resolve,也就是在then方法中进行成功的操作
// 失败时执行reject,也就是在catch方法中进行失败操作
将setTimeout封装为Promise
const myTimeOut= function(time){
const promise = new Promise(function(resolve, reject){
setTimeout(()=>{
//成功时调用
resolve('Hello World')
},time)
}
return promise
};
myTimeOut(1000).then(data=>{
console.log(data, '执行timeout')
})
Promise三种状态
- pending: 等待状态,比如正在进行网络请求,或者定时器没有到时间.
- fullfill:满足状态,我们会主动回调了resolve时,就处于该状态,并且会回调.then()
- reject: 拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()
Promise另一种写法
不写.catch方法, 在then方法中传入两个函数, 函数1
为成功回调,函数2
为失败回调
new Promise((resolve, reject) => {
setTimeout(()=>{
if(/*成功*/){
resolve('Hello World')
}else{
reject('error')
}
})
}).then(data=>{ //
console.log(data);
},err=>{
console.log(err);
})
Promise的链式调用
在then
方法中返回new Promise()
即可继续.then()
实现链式调用
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
console.log(res, '第一层的10行处理代码');
return new Promise(resolve=>{
resolve(res+'111')
})
}).then(res=>{
console.log(res, '第二层的10行处理代码');
return new Promise(resolve =>{
resolve(res+'222')
})
}).then(res=>{
console.log(res, '第三层的10行处理代码')
})
简写
new Promise()
简写
//Promise.resolve(data)
//Promise.reject(data)
// 简写
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
console.log(res, '第一层的10行处理代码');
return Promise.resolve(res+'111')
}).then(res=>{
console.log(res, '第二层的10行处理代码');
if(/*失败*/){
return Promise.resolve(res+'222')
}else{
return Promise.reject('error message')
}
}).then(res=>{
console.log(res, '第三层的10行处理代码')
}).catch(err=>{
console.log(err)
})
再次简写
省略掉Promise.resolve()
在then()
中直接return
到时候内部是会对其进行一次Promise包装
省略掉Promise.reject()
在then()
中直接抛出异常即throw 'error message'
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
console.log(res, '第一层的10行处理代码');
return res+'111'
}).then(res=>{
console.log(res, '第二层的10行处理代码');
if(/*失败*/){
throw 'erroe message'
}else{
return res+'222'
}
}).then(res=>{
console.log(res, '第三层的10行处理代码')
}).catch(err=>{
console.log(err)
})
Promise的all()方法使用
当一个需求需要多个请求都返回数据才可以执行
传统做法
let res1 = false
let res2 = false
$.ajax({
url: '',
success: function(data){
console.log('结果1');
res1 = true
handleRes()
}
})
$.ajax({
url: '',
success: function(data){
console.log('结果2')
res2 = true
handleRes()
}
})
function handleRes(){
if(res1 && res2 ){
console.log('两个请求都拿到数据了')
}
}
这么写一方面不美观,维护起来也是比较麻烦,接下来用Promise实现上述需求
// all() 传入可迭代对象(数组)
// Promise 内部会帮你判断 这个两个请求是否都完成
// 如果都完成则会调用then方法
// results 是一个数组,results[0]则是第一个Promise的值,results[1]则是第二个Promise的值,以此类推
Promise.all([
new Promise((resolve,reject)=>{
$ajax({
url: 'url1',
success: function(data){
resolve(data)
}
})
}),
new Promise((resolve,reject)=>{
$ajax({
url: 'url2',
success: function(data){
resolve(data)
}
})
})
]).then(results =>{
console.log(results,'两个请求都成功了')
})