一:为什么会出现?
1、场景一:在很多业务需求中,你需要通过ajax进行多次请求,而且每次请求返回的数据需要作为参数进行下一次的请求,于是会出现ajax层层嵌套问题。多个请求操作层层依赖,加上每一层还会有复杂的业务逻辑需要处理,使得代码可读性很差,不直观,难以维护和调试。
注:这种回调函数层层嵌套又称为回调地狱
//请求A
$.ajax({
success:function(res1) {//请求B
$.ajax({
success:function(res2) {//请求C
$.ajax({
success:function(res3) {
......
.......
}
})
}
})
}
})
2、场景二:如果请求C依赖于请求A和B的结果,但A和B之间互不依赖,如果仍写成A嵌套B,B嵌套C的形式,无疑是会消耗更多的等待时间。
故出现Promise对象来更合理和规范地处理异步操作。JS中所有代码都是单线程执行,如果必须是异步执行,可以通过回调函数实现
二:如何使用?
Promise对象是全局对象,可以理解为一个类。
Promise对象有三种状态:
pending:刚创建实例,表示初始化状态
fulfilled:resolve方法调用的时候,表示操作成功
rejected:reject方法调用的时候,表示操作失败
1、通过new生成一个实例,参数是一个匿名函数,其中有两个参数resolve,reject
var pro = new Promise(function(resolve, reject) {
//pending状态if ('操作成功') {
resolve();//resolve:处理异步操作执行成功后的回调函数 fulfiied状态
} else{
reject();//reject:处理异步操作失败后的回调函数 rejected状态
}
})
2、then()方法:用于处理操作后的处理程序
pro.then(function(res) {//执行resolve回调函数
}, function(error) {//执行reject回调函数
})
3、catch()方法:处理操作异常的程序
pro.catch(function(error) {//执行reject回调函数
})
综合上面两个方法,一般用then方法处理操作成功的程序,catch用来处理操作异常的程序
pro.then(function(res) {//执行resolve回调函数
}).catch(function(error) {//执行reject回调函数
})
完整示例:最后输出结果为:执行成功
var pro = new Promise(function(resolve, reject) {//pending状态
if (true) {
resolve('执行成功');//resolve:处理异步操作执行成功后的回调函数 fulfiied状态
} else{
reject('执行失败');//reject:处理异步操作失败后的回调函数 rejected状态
}
})
pro.then(function(res) {//执行resolve回调函数
console.log(res)
}).catch(function(error) {//执行reject回调函数
console.log(error)
})
三:如何解决回调地狱问题?
var pro = new Promise(function(resolve, reject) {if (true) {
resolve('执行成功');
}else{
reject('执行失败');
}
})
pro.then(A)
.then(B)
.then(C)
.catch(D)functionA(res) {
console.log(res)//执行成功
return '给下一个B请求传参:成功执行A';
}functionB(res) {
console.log(res)//给下一个B请求传参:成功执行A
return '给下一个C请求传参:成功执行B';
}functionC(res) {
console.log(res)//给下一个C请求传参:成功执行B
}functionD(error) {
console.log(error)
}
可以通过多个then方法进行链式操作,通过return方式给下一个执行回调函数传参,如上示例的结果是
执行成功
给下一个B请求传参:成功执行A
给下一个C请求传参:成功执行B
四:如何解决场景二问题?
Promise.all()方法:当参数中的实例对象的状态都为fulfilled时,Promise.all()才会执行resolve函数
var pro1 = new Promise(function(resolve, reject) {
setTimeout(resolve('成功执行1'),5000);
});var pro2 = new Promise(function(resolve, reject) {
setTimeout(resolve('成功执行2'),1000);
});
Promise.all([pro1,pro2]).then(function(res) {
console.log(res)
})
pro1在1000ms以后成功进入fulfilled状态,但此时Promise.all还是不会有行动,需要等到pro2进入到fulfilled状态时,才会进入then方法,故5000ms以后执行结果为:
[
'成功执行1',
'成功执行2'
]
类似的方法还有Promise.race()方法,参数为Promise实例,只要有一个状态发生改变,不管是成功fulfiied还是失败rejected状态,就会有返回,其他实例再有变化也不会再处理了。
var pro1 = new Promise(function(resolve, reject) {
setTimeout(resolve,5000,'成功执行1');
});var pro2 = new Promise(function(resolve, reject) {
setTimeout(reject,1000,'失败执行2');
});
Promise.race([pro1,pro2]).then(function(res) {
console.log(res)
}).catch(function(error) {
console.log(error)
})
执行结果为:
失败执行2