在上一篇文我们说到了回调地狱不好的地方,今天我们看看怎么来优化它,让它可以运用到实际开发中。
什么是回调地狱?回调地狱就是一个函数里面嵌套了所有功能函数,然后缩略图形成一个三角形。
这样的代码可复用性不强。阅读性差也代表可维护性差。扩展性也差。
也不符合设计模式的六大原则, 其中的 单一职责原则, 和 开闭原则
单一职责原则:尽量让一个函数只做一件事情
开闭原则:函数应该对扩展开放,对修改关闭
---------------------------------------------------------------------
我们先来看一下未优化前的代码,未优化前的代码同样可以实现该功能。
但只适合小公司开发,因为没有人去看你的代码,大公司还是需要优化的
代码如下:
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>Document</title> 9 <style> 10 * { 11 padding: 0px; 12 margin: 0px; 13 } 14 15 .tpl { 16 display: none; 17 } 18 19 .wrapper { 20 overflow: hidden; 21 border: 2px solid black; 22 600px; 23 margin: 100px auto 0px; 24 } 25 26 .movieSection { 27 float: left; 28 180px; 29 height: 180px; 30 padding: 10px; 31 } 32 33 .movieSection img { 34 100%; 35 height: 150px; 36 cursor: pointer; 37 } 38 39 .movieSection h3 { 40 height: 30px; 41 } 42 </style> 43 </head> 44 45 <body> 46 <div class="wrapper"> 47 <div class="tpl"> 48 <img></img> 49 <h3 class="movieName"></h3> 50 </div> 51 </div> 52 <script src="../jq/jquery-3.3.1/jquery-3.3.1.js"></script> 53 <script> 54 55 //模拟电影网站,判断用户是否为该网址的vip用户(最高权限为vip) 56 //如果vpi就展示出vip电影,点击相应的电影显示出该电影的详细介绍 57 58 59 //发送网络请求 60 $.ajax({ 61 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power', //向此服务器请求 62 type: 'POST', //获取数据类型 63 data: { //假设传入了账号密码,已经验证成功了。为了演示我们就不写input框来输入了 64 username: 'ypx', 65 password: '123' 66 }, 67 success: function (res) { //请求成功后执行的函数 68 if (res.data.power == 'root') { //判断该用户是否为最高vip,如果是就返回出vip电影资源 69 //vip 网络地址发送请求 70 $.ajax({ 71 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList', 72 //正常开发中,数据不应该在这拿, 73 //应该在请求返回来的res中获取数据的,我们现在为了演示就在这里获取第二次数据了 74 75 type: 'GET', 76 success: function (res) { 77 var data = res.data; //声明一个变量为获取到的数据 78 var $Wrapper = $('.wrapper'); //获取wrapper准备存放数据 79 $.each(data, function (index, ele) { //循环所有数据里面的东西 80 //ele.name 数据里面的电影名称 ele.poster 数据里面的海报地址 81 82 var $MovieSection = $('.tpl').clone().removeClass('tpl').addClass('movieSection'); 83 //把HTML结构的模板给克隆过来存放数据,再把模板的类名换成要放数据结构的类名 84 85 $MovieSection.data({ id: ele.id }).on('click', function () {//给获取数据加上id,添加点击事件 86 $.ajax({ 87 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo', 88 type: 'GET', 89 data: { 90 movieId: $(this).data('id') //点击谁this就指向谁 91 }, 92 success: function (res) { 93 var data = res.data; 94 var direct = data.direct; 95 var gut = data.gut; 96 var mainActor = data.mainActor; 97 var screenWriter = data.screenwriter; 98 var htmlStr = '<div class="mask"> 99 <p>导演: ' + direct + '</p> 100 <p>剧情: ' + gut + '</p> 101 <p>主演: ' + mainActor.reduce(function (prev, curv) { 102 prev += curv + ' '; 103 return prev; 104 }, '') + '</p> 105 <p>编剧: ' + screenWriter.reduce(function (prev, curv) { 106 prev += curv + ' '; 107 return prev; 108 }, '') + '</p> 109 </div>' 110 $(htmlStr) //把数据结构加到body里面 111 .appendTo('body'); 112 } 113 }); 114 }) 115 .children() //获取克隆后的模板结构下面的所有子元素 116 .eq(0) //选中元素中的第一个 117 .attr('src', ele.poster) //给属性加上数据中的海报 118 .next() //给下一个兄弟元素 119 .text(ele.name); //给文本加上数据中的电影名称 120 $Wrapper.append($MovieSection);//把MouseEvent填充到wrapper标签下面 121 }); 122 } 123 }) 124 } else { 125 //不是vip 126 } 127 } 128 }); 129 </script> 130 </body> 131 132 </html>
接下来我们具体来看是怎么优化的,最后会附上完整代码
第一步
判断该用户是否为VIP用户
第二步
确定为VIP用户,返回VIP资源
第三步
将资源的电影海报,电影名称可视化
第四步
添加点击事件,点击海报后显示出详情介绍
衔接上下图片↑↓
最后我们再来看一下成品图:
最后附上完整代码加注释:
1 (function () { 2 return $.ajax({ 3 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power', 4 type: 'POST', 5 data: { //获取账号密码 6 username: 'ypx', 7 password: '123' 8 }, 9 }); 10 })().then(function (res) { 11 if (res.data.power == 'root') { //判断该账号密码是否为最高权限(VIP用户),是的话就发送网络请求获取VIP用户的数据 12 return $.ajax({ 13 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList', 14 //正常开发中,数据不应该在这拿, 15 //应该在请求返回来的res中获取数据的,我们现在为了演示就在这里获取第二次数据了 16 17 type: 'GET' 18 }); 19 } 20 }).then(function (res) { 21 var data = res.data; //声明一个变量为获取到的数据 22 var $Wrapper = $('.wrapper'); //获取wrapper准备存放数据 23 var df = $.Deferred(); 24 $.each(data, function (index, ele) { //循环所有数据里面的东西 25 //ele.name 数据里面的电影名称 ele.poster 数据里面的海报地址 26 27 var $MovieSection = $('.tpl').clone().removeClass('tpl').addClass('movieSection'); 28 //把HTML结构的模板给克隆过来存放数据,再把模板的类名换成要放数据结构的类名 29 30 $MovieSection.data({ id: ele.id }) 31 .on('click', function () { //在这里添加点击事件,由于在里面返回数据外面会接收不到,所以我们在里面弄一个注册成功可以返回 32 df.resolve(); //注册成功 33 }) 34 .children() //获取克隆后的模板结构下面的所有子元素 35 .eq(0) //选中元素中的第一个 36 .attr('src', ele.poster) //给属性加上数据中的海报 37 .next() //给下一个兄弟元素 38 .text(ele.name); //给文本加上数据中的电影名称 39 $Wrapper.append($MovieSection); //把MouseEvent填充到wrapper标签下面 40 }); 41 return df.promise(); //只返回注册方法,不返回出执行方法 42 }).then(function (res) { 43 return $.ajax({ 44 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo', 45 type: 'GET', 46 data: { 47 movieId: $(this).data('id') //点击谁this就指向谁 48 } 49 }); 50 }).then(function(res){ 51 var data = res.data; 52 var direct = data.direct; 53 var gut = data.gut; 54 var mainActor = data.mainActor; 55 var screenWriter = data.screenwriter; 56 var htmlStr = '<div class="mask"> 57 <p>导演: ' + direct + '</p> 58 <p>剧情: ' + gut + '</p> 59 <p>主演: ' + mainActor.reduce(function (prev, curv) { 60 prev += curv + ' '; 61 return prev; 62 }, '') + '</p> 63 <p>编剧: ' + screenWriter.reduce(function (prev, curv) { 64 prev += curv + ' '; 65 return prev; 66 }, '') + '</p> 67 </div>' 68 $(htmlStr) //把数据结构加到body里面 69 .appendTo('body'); 70 });
谢谢观看!!! 谢谢观看!!! 谢谢观看!!!