ES6 Promise 详解
目录
一、Promise基本介绍
(1) Ajax方式的异步调用在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,称为"Callback Hell" (回调地狱)。
(2) Promise即是异步编程的一种解决方案,早在 ECMAScript 2015 (ES6) 中便成为标准。
(3) 从语法层面讲,Promise是一个对象,用来获取异步操作的信息。
二、Promise实现多次请求
1.传统Ajax方式实现多次请求 :
1.1 json数据准备
通过student和student_detail_1两个json文件来简单模拟测试数据;第一次请求得到student.json中保存的数据,第二次请求通过前一次请求得到的数据,进一步得到student_detail_1.json中保存的数据(即先得到student.json中的id属性,根据该属性进一步得到student_detail_1.json中的更多属性)。
student.json代码如下 :
{
"id" : 1,
"name" : "Cyan"
}
student_detail_1.json代码如下 :
{
"id" : 1,
"name" : "Cyan",
"age" : 21,
"score" : 450
}
1.2 JQuery操作Ajax
traditional_ajax.html代码如下 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Traditional Asynchronous</title>
<!-- 此处的src使用了相对路径。 -->
<script type="text/javascript" src="../script/jquery-3.7.0.min.js"></script>
<script type="text/javascript">
/*
PS : JQuery操作Ajax回顾 :
$.ajax函数的常用参数如下———
(1) url : 请求的地址
(2) type : 请求的方式GET or POST
(3) data : 发送到服务器端的数据,将自动转换为请求字符串格式
(4) success : 成功的回调函数
(5) dataType : 返回的数据类型,常用Json或text。
*/
$.ajax({
url:"../data/student.json",
// type: ,
// data: ,
success:function (resultData) {
console.log("The 1st request,and the student's basic information is :",resultData);
//从第二次异步请求开始,已经出现了"ajax嵌套"
$.ajax({
url:`../data/student_detail_${resultData.id}.json`,
success(resultData) {
console.log("The 2nd request,and the student's detailed information is :",resultData)
},
error(errInfo) {
console.log("Oh oh,Something bad happened:",errInfo);
}
})
},
error(errInfo) { //ES6新特性————对象的方法简写。
console.log("Something bad happened:",errInfo);
}
})
</script>
</head>
<body>
</body>
</html>
运行结果 :
2.使用ES6新特性Promise方式 :
数据部分仍然使用data包下的student.json和student_detail_1.json。
promise.html代码如下 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Promise Demonstration</title>
<script type="text/javascript" src="../script/jquery-3.7.0.min.js"></script>
<script type="text/javascript">
//1.首先请求data包下的student.json(需要创建一个Promise对象)
//创建Promise对象时需要传入一个箭头函数
//形参resolve表示请求成功的回调函数;形参reject表示请求失败的回调函数。
//形参resolve和reject是约定俗成的,不固定,可以自由更改名称。
let promise = new Promise((resolve,reject) => {
//发出Ajax异步请求
$.ajax({
url:"../data/student.json",
// type:
// data:
// dataType:
success(resultData) {
console.log("Promise's 1st request,and the student's basic information is :",resultData);
//该方法将resultData参数传递到then()
resolve(resultData);
},
error(errInfo) {
// console.log("Promise's 1st request---Perhaps sth bad happened:",errInfo);
//使用ES6---Promise提供的catch机制来统一处理异常
reject(errInfo);
}
})
})
//2.第二次请求在这里执行!
promise.then(resultData => { //箭头函数形参的简写
// 调用链, 通过return将Promise对象返回给下一个调用者。
return new Promise((resolve, reject) => {
$.ajax({
//url采用了模板字符串的形式
url:`../data/student_detail_${resultData.id}.json`,
success(resultData) {
console.log("Promise's 2nd request,and the student's detailed information is :",resultData);
/*
可以在第二次请求的success回调函数里,
继续使用resolve(resultData);发出第三次请求。
*/
resolve(resultData);
},
error(errInfo) {
// console.log("Promise's 2nd request---Perhaps sth bad happened:",errInfo);
reject(errInfo);
}
})
})
}).then(resultData => {
/*
(1)此处输出的resultData,来自第二次Ajax请求的success中的"resolve(resultData);"
(2)可以在这个then方法中,继续通过
"return new Promise((resolve, reject) => { $.ajax({}) })"
的方式来发出第三次Ajax异步请求。
(3)第三次Ajax异步请求,是基于第二次Ajax请求获取的数据resultData。
*/
console.log("After 2nd request, THE resultData =",resultData);
}).catch(errInfo => {
console.log("U~ Promise's request---Perhaps sth bad happened:",errInfo);
})
</script>
</head>
<body>
</body>
</html>
运行结果 :
三、Promise代码重排优化
1.问题分析 :
使用Primise方式代替传统Ajax方式发送多次异步请求之后,以“链式调用”代替了“嵌套调用”,可读性提升。
但仍然存在“代码臃肿”,“代码重复度高”的特点;因此,可以通过代码重排进行优化。
2.代码优化 :
2.1 数据准备
在data包下新建一个json文件,用来模拟student1的监护人的数据。
custodian_1.json代码如下 :
{
"id" : 1,
"phonetic" : "/kʌˈstoʊdiən/",
"father": "f1",
"mother": "m1",
"telephone": 5204505
}
2.2 代码重排
promise_EX.html代码如下 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To Optimize Promise</title>
<script type="text/javascript" src="../script/jquery-3.7.0.min.js"></script>
<script type="text/javascript">
/**
* @function 将多次请求相似的代码封装到一个方法中
* @param url : 请求的资源
* @param data : 请求时携带的数据
* @returns {Promise<unknown>}
*/
function getRequest(url, data) {
return new Promise((resolve, reject) => {
$.ajax({
url:url,
data:data,
success(resultData) {
resolve(resultData);
},
error(err) {
reject(err);
}
})
})
}
//1.第一次请求 --- 得到student.json中保存的数据
getRequest("../data/student.json").then(resultData => {
console.log("student =", resultData);
//2.第二次请求 --- 得到student_detail_1.json中保存的数据
return getRequest(`../data/student_detail_${resultData.id}.json`).then(resultData => {
console.log("student_1 =", resultData);
//3.第三次请求 --- 得到custodian_1.json中保存的数据
return getRequest(`../data/custodian_${resultData.id}.json`).then(resultData => {
console.log("custodian_1 =",resultData);
})
})
}).catch(err => {
console.log("Perhaps something bad happened:",err);
})
</script>
</head>
<body>
</body>
</html>
运行结果 :
System.out.println("END------------------------------------------------------------");