回調地獄
什么是回調地獄,回調函數,一個嵌套着一個,到最后,縮略圖成了 一個三角形, 造成了可閱讀性差,可閱讀性差就代表代碼的可維護性 和 可迭代性差,最后還有一個就是可擴展性差。
也不符合設計模式的六大原則, 其中的 單一職責原則, 和 開閉原則
單一職責原則: 盡量讓一個函數只做一件事情
開閉原則:函數應該對擴展開放,對修改關閉
接下來看一下什么是回調地獄:
小案例的效果圖:
下面的代碼雖然能實現這個功能,但是如果按照這種做法,功能一多,回調函數會一個嵌套一個, 最后的代碼會形成一個三角區。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>Document</title> 8 <style> 9 * { 10 padding: 0px; 11 margin: 0px; 12 } 13 14 .tpl { 15 display: none; 16 } 17 18 .wrapper { 19 overflow: hidden; 20 border: 2px solid black; 21 width: 600px; 22 margin: 100px auto 0px; 23 } 24 .movieSection { 25 float: left; 26 width: 180px; 27 height: 180px; 28 padding: 10px; 29 } 30 31 .movieSection img { 32 width: 100%; 33 height: 150px; 34 cursor: pointer; 35 } 36 37 .movieSection h3 { 38 height: 30px; 39 } 40 </style> 41 </head> 42 <body> 43 <!-- 基本結構 --> 44 <div class="wrapper"> 45 <div class='tpl'> 46 <img src=""></img> 47 <h3 class='movieName'></h3> 48 </div> 49 </div> 50 51 <script src='./jquery.js'></script> 52 <script> 53 $.ajax({ 54 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power', 55 type: 'POST', 56 data: { 57 username: 'fsfs', 58 password: '123123' 59 }, 60 success: function (res) { //一個回調函數,解決了全部事情,因為下面的代碼 都是在這個回調里面。 61 if (res.data.power == 'root') { 62 $.ajax({ //如果賬號密碼正確, 執行 success 回調 請求數據 63 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList', 64 type: 'GET', 65 success: function (res) { //如果 請求成功, 執行回調以下拿到數據渲染 頁面 66 console.log(res) 67 var data = res.data; 68 var $Wrapper = $('.wrapper'); 69 $.each(data, function(index, ele) { 70 var $MovieSection = $('.tpl').clone().removeClass('tpl').addClass('movieSection'); 71 $MovieSection.data({id: ele.id}).on('click', function (){//添加點擊事件 再次請求 詳細文字頁面 72 73 $.ajax({ 74 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo', 75 type: 'GET', 76 data: { 77 movieId: $(this).data('id') 78 }, 79 success: function (res) { //如果請求數據成功,執行回調再次添加 數據到頁面 80 var data = res.data; 81 var direct = data.direct; 82 var gut = data.gut; 83 var mainActor = data.mainActor; 84 var screenWriter = data.screenwriter; 85 86 var htmlStr = '<div class="mask">\ 87 <p>導演: ' + direct + '</p>\ 88 <p>劇情: ' + gut + '</p>\ 89 <p>主演: ' + mainActor.reduce(function (prev, curv) { 90 prev += curv + ' '; 91 return prev; 92 }, '') + '</p>\ 93 <p>編劇: ' + screenWriter.reduce(function (prev, curv) { 94 prev += curv + ' '; 95 return prev; 96 }, '') + '</p>\ 97 </div>' 98 99 $(htmlStr).appendTo('body') 100 101 } 102 }); 103 }).children() 104 .eq(0).attr('src', ele.poster) 105 .next().text(ele.name); 106 107 $Wrapper.append($MovieSection); 108 }); 109 } 110 }) 111 }else { 112 113 } 114 } 115 }); 116 117 </script> 118 </body> 119 </html>
下面利用 $.Deferred() 和 .then() 解決回調地獄, 並沒有形成三角區,而是直線,而且一個回調函數只做一件事。 不像上面的 第一個回調函數一樣,一個回調函數,做了全部事情
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>Document</title> 8 <style> 9 * { 10 padding: 0px; 11 margin: 0px; 12 } 13 14 .tpl { 15 display: none; 16 } 17 18 .wrapper { 19 overflow: hidden; 20 border: 2px solid black; 21 width: 600px; 22 margin: 100px auto 0px; 23 } 24 .movieSection { 25 float: left; 26 width: 180px; 27 height: 180px; 28 padding: 10px; 29 } 30 31 .movieSection img { 32 width: 100%; 33 height: 150px; 34 cursor: pointer; 35 } 36 37 .movieSection h3 { 38 height: 30px; 39 } 40 </style> 41 </head> 42 <body> 43 <!-- 基本結構 --> 44 <div class="wrapper"> 45 <div class='tpl'> 46 <img src=""></img> 47 <h3 class='movieName'></h3> 48 </div> 49 </div> 50 51 <script src='./jquery.js'></script> 52 <script> 53 54 (function () { //實際上返回ajax ,是返回ajax 里面的 deferred.promise 對象 55 return $.ajax({//把ajax 返回出去。外面可以.then 可以拿到 done回調函數 56 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power', 57 type: 'POST', 58 data: { 59 username: 'fafa', 60 password: '123123' 61 } 62 }); 63 })() 64 .then(function (res) { 65 if (res.data.power == 'root') { 66 return $.ajax({ 67 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList', 68 type: 'GET', 69 }); 70 } 71 }) 72 .then(function (res) { 73 var data = res.data; 74 var $Wrapper = $('.wrapper'); 75 var df = $.Deferred(); 76 $.each(data, function(index, ele) { 77 // ele.name ele.poster 78 var $MovieSection = $('.tpl').clone().removeClass('tpl').addClass('movieSection'); 79 $MovieSection 80 .data({id: ele.id}) 81 .on('click', function () { 82 df.resolve( $(this) ); 83 }) 84 .children() 85 .eq(0).attr('src', ele.poster) 86 .next().text(ele.name); 87 $Wrapper.append($MovieSection); 88 }); 89 return df.promise(); 90 }) 91 .then(function (dom) { 92 return $.ajax({ 93 url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo', 94 type: 'GET', 95 data: { 96 movieId: dom.data('id') 97 } 98 }); 99 }) 100 .then(function (res) { 101 var data = res.data; 102 var direct = data.direct; 103 var gut = data.gut; 104 var mainActor = data.mainActor; 105 var screenWriter = data.screenwriter; 106 107 var htmlStr = '<div class="mask">\ 108 <p>導演: ' + direct + '</p>\ 109 <p>劇情: ' + gut + '</p>\ 110 <p>主演: ' + mainActor.reduce(function (prev, curv) { 111 prev += curv + ' '; 112 return prev; 113 }, '') + '</p>\ 114 <p>編劇: ' + screenWriter.reduce(function (prev, curv) { 115 prev += curv + ' '; 116 return prev; 117 }, '') + '</p>\ 118 </div>' 119 120 $(htmlStr).appendTo('body') 121 }); 122 123 124 125 </script> 126 </body> 127 </html>