目录
一、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------------------------------------------------------------");