一、promise出现的原因
在promise出现以前,我们处理多个异步请求,代码大概如下:
请求1(function(请求结果1){
请求2(function(请求结果2){
请求3(function(请求结果3){
请求4(function(请求结果4){
请求5(function(请求结果5){
请求6(function(请求结果3){
...
})
})
})
})
})
})
这便是臭名昭著的回调地狱,我们需要根据第一个网络请求结果,再去执行第二个网络请求,还要对每次请求的结果进行一些处理,代码会更加臃肿,在一个团队中,代码review以及后续的维护将会是一个痛苦的过程。
回调地狱带来的负面作用有以下几点:
代码臃肿。
可读性差。
耦合度过高,可维护性差。
代码复用性差。
容易滋生 bug。
只能在回调里处理异常。
出现了问题,自然就会有人去想办法。这时候,就有人思考,能不能用一种更加友好的代码组织方式,解决异步嵌套的问题。
let 请求结果1 = 请求1();
let 请求结果2 = 请求2(请求结果1);
let 请求结果3 = 请求3(请求结果2);
let 请求结果4 = 请求4(请求结果3);
let 请求结果5 = 请求5(请求结果4);
类似上面这种异步的写法,于是promise规范诞生了
二、什么是Promise
Promise是异步编程的一种解决方案,我们使用promise的时候会将函数的状态凝固,,比传统的异步解决方案(回调函数和事件)更合理,现已被es6纳入规范中。
Promise书写格式
对于上面的网络请求,Promise的常规写法:
new Promise(请求1)
.then(请求2(请求结果1))
.then(请求3(请求结果2))
.then(请求4(请求结果3))
.then(请求5(请求结果4))
.catch(处理异常(异常信息))
三、promise的api
resolve和reject
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”,在异步操作失败时调用,并将操作失败操作报出的错误,作为参数传递出去。
then和catch
var p = new Promise((resolve,reject)=>{
resolve("success");
reject("fail")
})
p.then(res=>{
console.log(res);//成功,输出success
}).catch(err=>{
console.log(err);//失败,输出fail
})
then触发的是resolve的状态,即成功时的状态
catch触发的是reject的状态,即失败时的反馈
四、promise封装ajax请求
function http(){
return new Promise((resolve,reject)=>{
$.ajax({
url:"https://music.aityp.com/top/playlist?cat=华语",
type:"get",
success:res=>{
resolve(res)
},
error:err=>{
reject(err)
}
})
})
}
http().then(res=>{
console.log(res.data.playlists);
})
五、Promise一些static方法
5-1 Promise.all
参考链接:理解和使用Promise.all和Promise.race
const p = Promise.all([p1, p2, p3])
只有p1,p2,p3三个状态都是fulfilled的时候,p的状态才会是fulfilled。其中有一个rejected,p的状态就会变成rejected。下面是使用实例
需要特别注意的是,Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的,即p1的结果在前(即使p1的结果获取的比p2要晚)。这带来一个很大的好处:在前端开发请求数据的过程中,偶尔会遇到发送多个请求并根据请求顺序获取的使用数据的场景,使用Promise.all可以很好解决这个问题。
5-2 Promise.race
顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。