最近我在看一个uniAPP项目的源码,本是无意翻翻看,却偶然看到了这样一段代码
uni.addInterceptor({
returnValue(res) {
if(!isPromise(res)) {
return res;
}
return new Promise((resolve, reject) => {
res.then((res) => {
if(res[0]) {
reject(res[0]);
} else {
resolve(res[1]);
}
});
});
},
});
} catch(err) {}
发现我看不懂这段代码的逻辑。然后我去搜索引擎搜了一下。
这段代码大概是这个意思:
该段代码是一个拦截器,用于处理返回值。具体来说,它检查返回值是否为Promise类型,
如果是,就通过Promise处理函数进行处理,并将处理结果返回给调用方。
代码中的`uni`是uniAPP类的一个实例,其`addInterceptor`方法用于添加拦截器。该拦截器有一个名为`returnValue`的处理函数,该函数接收一个参数`res`,用于处理返回值。
如果返回值`res`不是Promise类型,则直接将其返回。如果`res`是Promise类型,则通过Promise处理函数进行处理,并返回处理结果。
具体来说,处理函数首先检查Promise对象是否被成功解析(即是否执行了`resolve`方法)。
如果Promise对象被成功解析,则将解析结果作为处理结果返回。如果Promise对象被拒绝(即执行了`reject`方法),则将拒绝原因作为错误信息抛出(即通过`reject(res[0)`抛出)。
在try...catch 块中使用 uni.addInterceptor 可能是因为 addInterceptor 方法可能会抛出错误,为了避免该错误影响程序的正常执行,使用 try...catch 块来捕获可能的错误。
其中Promise是异步编程的一种解决方案。
因为传统的Ajax异步调用在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的Callback Hell
For Example:
Student.json:
{
"id":1,
"name":"诉衷情の麻雀"
}
Student_detail_1.json
{
"id":1,
"address":"中国洛阳",
"age":18
}
然后我用Ajax发送第一次请求
<script type="text/javascript">
//jquery发出ajax的方式
$.ajax({
url: "data/Student.json",
success(resultData) {//如果请求成功了,回调处理函数success
console.log("第1次ajax请求 Student基本信息=", resultData);
},
error(err) {
console.log("出现异常=", err);
}
})
</script>
第一次请求成功,那么我再用Ajax发送第二次请求
<script type="text/javascript">
//jquery发出ajax的方式
$.ajax({
url: "data/Student.json",
success(resultData) {//如果请求成功了,回调处理函数success
console.log("第1次ajax请求 Student基本信息=", resultData);
$.ajax({
url:`data/Student_detail_${resultData.id}.json`,
success(resultData) {
console.log("第2次Ajax请求的Student的详细信息",resultData)
},error(err) {
console.log("出现异常")
}
})
},
error(err) {
console.log("出现异常=", err);
}
})
</script>
同样我们是拿到student的详细信息了
如果我们要发送第三次、第四次Ajax请求呢?那是不是要在success继续嵌套多个Ajax
所以这种写法代码冗余度较高,不易维护。
因此Promise就是为了解决这个问题应运而生
下面我将演示用Promise发送Ajax请求
<script type="text/javascript">
//先请求到Student.json
//1. 创建Promise对象
//2. 构造函数传入一个箭头函数
//3.(resolve, reject)参数列表resolve: 如果请求成功,调用resolve函数
//4. 如果请求失败,调用reject函数
//5. 箭头函数体,仍然是通过jQuery发出了Ajax请求
let p = new Promise((resolve,reject) => {
//发出Ajax请求
$.ajax({
url:"data/Student.json",
success(resultData) { //成功的回调函数
console.log("promise发出的一次Ajax Student基本信息:" ,resultData);
},
error(err) {
console.log("promise 发出的异步请求异常: ", err);
}
})
})
</script>
得出来的结果
下面我用Promise发出第二次Ajax请求
<script type="text/javascript">
//先请求到Student.json
//1. 创建Promise对象
//2. 构造函数传入一个箭头函数
//3.(resolve, reject)参数列表resolve: 如果请求成功,调用resolve函数
//4. 如果请求失败,调用reject函数
//5. 箭头函数体,仍然是通过jQuery发出了Ajax请求
let p = new Promise((resolve,reject) => {
//发出Ajax请求
$.ajax({
url:"data/Student.json",
success(resultData) { //成功的回调函数
console.log("promise发出的一次Ajax Student基本信息:" ,resultData);
resolve(resultData);
},
error(err) {
console.log("promise 发出的异步请求异常: ", err);
}
})
})
//这里我们继续可以编写请求成功后的业务
p.then((resultData) => {
//这里我们可以继续发出请求
console.log("p.then 得到ResultData",resultData);
$.ajax({
url:`data/Student_detail_${resultData.id}.json`,
success(resultData) {
console.log("第2次Ajax请求 Student的详细信息=",resultData);
},
error(err) {
console.log("Promise发出的异步请求异常=", err);
}
})
})
</script>
结果:
其中Resolve函数名称也可以写成别的函数名字,只要前后保持一致也是可以运行的
所以这里的resolve只是个形参,具体的执行流程感兴趣的小伙伴可以看下源码。
其中我们可以在error中调用reject(err)。在p.then后面加上catch语句,这样不论是第一次请求还是第二次都能在catch语句中统一捕获抛出异常。
但要注意的是第二次请求的Promise对象要return出去,这样catch语句才能执行。
<script type="text/javascript">
//先请求到Student.json
//1. 创建Promise对象
//2. 构造函数传入一个箭头函数
//3.(resolve, reject)参数列表resolve: 如果请求成功,调用resolve函数
//4. 如果请求失败,调用reject函数
//5. 箭头函数体,仍然是通过jQuery发出了Ajax请求
let p = new Promise((resolve,reject) => {
//发出Ajax请求
$.ajax({
url:"data/Student.json",
success(resultData) { //成功的回调函数
console.log("promise发出的一次Ajax Student基本信息:" ,resultData);
resolve(resultData);
},
error(err) {
reject(err)
}
})
})
//这里我们继续可以编写请求成功后的业务
p.then((resultData) => {
//这里我们可以继续发出请求
// console.log("p.then 得到ResultData",resultData);
return new Promise((resolve, reject) => {
$.ajax({
url:`data/Student_detail_${resultData.id}.json`,
success(resultData) {
console.log("第2次Ajax请求 Student的详细信息=",resultData);
},
error(err) { //第二次Ajax请求失败的回调函数
reject(err)
}
})
})
}).catch((err)=> {
console.log("Promise发出的异步请求异常=", err);
})
</script>
接下来再新建一个studentfri.json
这样演示第三次请求时依赖于第二次请求的结果,将使用模板字符串把resultData.fri获取到,然后去请求Student_fri_2.json。
<script type="text/javascript">
//先请求到Student.json
//1. 创建Promise对象
//2. 构造函数传入一个箭头函数
//3.(resolve, reject)参数列表resolve: 如果请求成功,调用resolve函数
//4. 如果请求失败,调用reject函数
//5. 箭头函数体,仍然是通过jQuery发出了Ajax请求
let p = new Promise((resolve,reject) => {
//发出Ajax请求
$.ajax({
url:"data/Student.json",
success(resultData) { //成功的回调函数
console.log("promise发出的一次Ajax Student基本信息:" ,resultData);
resolve(resultData);
},
error(err) {
reject(err)
}
})
})
//这里我们继续可以编写请求成功后的业务
p.then((resultData) => {
//这里我们可以继续发出请求
// console.log("p.then 得到ResultData",resultData);
return new Promise((resolve, reject) => {
$.ajax({
url:`data/Student_detail_${resultData.id}.json`,
success(resultData) {
console.log("第2次Ajax请求 Student的详细信息=",resultData);
resolve(resultData);
},
error(err) { //第二次Ajax请求失败的回调函数 依赖于第一次请求的结果
reject(err)
}
})
})
}).then((resultData) => {
console.log("p.then().then(), resultData",resultData)
//即可以在这里发送第三次Ajax请求 依赖于第二次发出的结果 去获取他的朋友
return new Promise((resolve,reject) =>{
$.ajax({
url:`data/Student_fri_${resultData.fri}.json`,
success(resultData) { //第二次请求成功,回调函数
console.log("第3次Ajax请求,student的friend",resultData);
},error(err){
reject(err)
}
})
})
})
.catch((err)=> {
console.log("Promise发出的异步请求异常=", err);
})
</script>
结果:
这就是使用Promise发出Ajax请求的流程。但是代码看起来比较臃肿
我们对Promise进行代码重排。
<script type="text/javascript">
/**将重复的代码抽取出来,编写一个方法get
* @param url ajax请求的资源
* @param data ajax请求携带的数据
*
*/
function get(url, data) {
return new Promise((resolve, reject)=>{
$.ajax({
url:url,
data:data,
success(resultData) {
resolve(resultData);
},
error(err){
reject(err);
}
})
})
}
get("data/Student.json").then((resultData)=>{
//第1次Ajax请求成功后的处理代码
console.log("第一次Ajax请求返回的数据:" ,resultData);
return get(`data/Student_detail_${resultData.id}.json`);
}).then((resultData)=> {
//第2次Ajax请求成功后的处理代码
console.log("第2次Ajax请求成功后返回的数据:" ,resultData);
return get(`data/Student_fri_${resultData.fri}.json`);
}).then((resultData) => {
console.log("第三次ajax请求返回的数据=", resultData);
}).catch((err)=>{
console.log("Promise请求异常",err)
})
</script>